diff --git a/src/firefly/js/ui/tap/WavelengthPanel.jsx b/src/firefly/js/ui/tap/WavelengthPanel.jsx index edf5524f8..3d2614ed1 100644 --- a/src/firefly/js/ui/tap/WavelengthPanel.jsx +++ b/src/firefly/js/ui/tap/WavelengthPanel.jsx @@ -6,7 +6,7 @@ import {CheckboxGroupInputField} from '../CheckboxGroupInputField.jsx'; import {FieldGroupCtx, ForceFieldGroupValid} from '../FieldGroup.jsx'; import {ListBoxInputField} from '../ListBoxInputField.jsx'; import {RadioGroupInputField} from '../RadioGroupInputField.jsx'; -import {useFieldGroupRerender, useFieldGroupWatch} from '../SimpleComponent.jsx'; +import {useFieldGroupRerender, useFieldGroupValue, useFieldGroupWatch} from '../SimpleComponent.jsx'; import {ValidationField} from '../ValidationField.jsx'; import {makeAdqlQueryRangeFragment, ConstraintContext, siaQueryRange} from './Constraints.js'; import { @@ -20,6 +20,15 @@ const panelTitle = 'Spectral Coverage'; const panelValue = 'Wavelength'; const panelPrefix = getPanelPrefix(panelValue); +const obsCoreWvlFieldKeys = { + selectionType: 'obsCoreWavelengthSelectionType', + rangeType: 'obsCoreWavelengthRangeType', + wvlContains: 'obsCoreWavelengthContains', + wvlMin: 'obsCoreWavelengthMinRange', + wvlMax: 'obsCoreWavelengthMaxRange', + wvlUnits: 'obsCoreWavelengthUnits', +}; + function getExponent(units) { switch (units) { case 'nm': return 'e-9'; @@ -30,17 +39,18 @@ function getExponent(units) { } -function makeWavelengthConstraints(wavelengthSelection, rangeType, filterDefinitions, fldObj) { +function makeWavelengthConstraints(filterDefinitions, fldObj) { const errList= makeFieldErrorList(); const siaConstraints= []; const adqlConstraintsAry = []; - const {obsCoreWavelengthContains:wlContains, obsCoreWavelengthMinRange:wlMinRange, - obsCoreWavelengthMaxRange:wlMaxRange, obsCoreWavelengthUnits:wlUnits}= fldObj; + const {[obsCoreWvlFieldKeys.selectionType]:wavelengthSelection, [obsCoreWvlFieldKeys.rangeType]:rangeType, + [obsCoreWvlFieldKeys.wvlContains]:wlContains, [obsCoreWvlFieldKeys.wvlMin]:wlMinRange, + [obsCoreWvlFieldKeys.wvlMax]:wlMaxRange, [obsCoreWvlFieldKeys.wvlUnits]:wlUnits} = fldObj; // pull out the fields we care about - if (wavelengthSelection === 'filter') { + if (wavelengthSelection?.value === 'filter') { const rangeList = []; filterDefinitions.forEach((filterDefinition) => { const fieldKey = 'filter' + filterDefinition.name; @@ -65,9 +75,9 @@ function makeWavelengthConstraints(wavelengthSelection, rangeType, filterDefinit // Need at least one field to be non-empty errList.addError('at least one filter must be checked'); } - } else if (wavelengthSelection === 'numerical') { + } else { //wavelengthSelection fld is undefined (because of no filters), or 'numerical' (radio option) const exponent= getExponent(wlUnits?.value); - if (rangeType === 'contains') { + if (rangeType?.value === 'contains') { errList.checkForError(wlContains); if (wlContains?.valid) { const range = wlContains.value; @@ -81,7 +91,7 @@ function makeWavelengthConstraints(wavelengthSelection, rangeType, filterDefinit } } } - if (rangeType === 'overlaps') { + if (rangeType?.value === 'overlaps') { errList.checkForError(wlMinRange); errList.checkForError(wlMaxRange); const anyHasValue = wlMinRange?.value || wlMaxRange?.value; @@ -109,29 +119,170 @@ function makeWavelengthConstraints(wavelengthSelection, rangeType, filterDefinit const checkHeaderCtl= makeCollapsibleCheckHeader(getPanelPrefix(panelValue)); const {CollapsibleCheckHeader, collapsibleCheckHeaderKeys}= checkHeaderCtl; -const fldKeys= ['obsCoreWavelengthContains', 'obsCoreWavelengthMinRange','obsCoreWavelengthSelectionType', - 'obsCoreWavelengthRangeType', 'obsCoreWavelengthMaxRange', 'obsCoreWavelengthUnits']; -export function ObsCoreWavelengthSearch({initArgs, serviceLabel, slotProps,useSIAv2}) { +export function WavelengthOptions({initArgs, fieldKeys, filterDefinitions, slotProps }) { + const [getSelectionType,] = useFieldGroupValue(fieldKeys.selectionType); + const [getRangeType,] = useFieldGroupValue(fieldKeys.rangeType); + + const hasFilters = filterDefinitions?.length > 0; + const useNumerical = !hasFilters || getSelectionType() === 'numerical'; + + const units = ( + + + + + ); + + return ( + + {hasFilters && ( + + )} + + {hasFilters && getSelectionType() === 'filter' && ( + + Require coverage at the approximate center of these filters: + + {filterDefinitions.map((filterDefinition) => ( + + ))} + + + )} + + {useNumerical && ( + +
+ +
+ {getRangeType() === 'contains' && ( +
+ +
+ )} + {getRangeType() === 'overlaps' && ( + + + to + + {units} + + )} +
+ )} +
+ ); +} + +WavelengthOptions.propTypes = { + initArgs: PropTypes.object, + fieldKeys: PropTypes.shape({ + selectionType: PropTypes.string, + rangeType: PropTypes.string, + wvlContains: PropTypes.string, + wvlMin: PropTypes.string, + wvlMax: PropTypes.string, + wvlUnits: PropTypes.string, + }).isRequired, + filterDefinitions: PropTypes.arrayOf(PropTypes.shape({ + name: PropTypes.string, + options: PropTypes.arrayOf(PropTypes.shape({ value: PropTypes.string, label: PropTypes.string })) + })), + slotProps: PropTypes.shape({ + selectionType: PropTypes.object, + rangeType: PropTypes.object, + wvlContains: PropTypes.object, + wvlMin: PropTypes.object, + wvlMax: PropTypes.object, + wvlUnits: PropTypes.object, + filterDefOptionsGroup: PropTypes.object, + numericalWvlOptions: PropTypes.object, + filterBandsWvlOptions: PropTypes.object, + }) +}; + + +export function ObsCoreWavelengthSearch({ initArgs, serviceLabel, slotProps, useSIAv2 }) { const filterDefinitions = getTapObsCoreOptions(serviceLabel).filterDefinitions ?? []; - const fdDefsKeys= filterDefinitions.length ? filterDefinitions.map((fd) =>'filter' +fd.name ) : []; + const fdDefsKeys = filterDefinitions.length ? filterDefinitions.map((fd) => 'filter' + fd.name) : []; + const fldKeys = Object.values(obsCoreWvlFieldKeys); - const {getVal,makeFldObj}= useContext(FieldGroupCtx); - const {setConstraintFragment}= useContext(ConstraintContext); + const { makeFldObj } = useContext(FieldGroupCtx); + const { setConstraintFragment } = useContext(ConstraintContext); const [constraintResult, setConstraintResult] = useState({}); - useFieldGroupRerender([...fldKeys,...fdDefsKeys, ...collapsibleCheckHeaderKeys]); // force rerender on any change + useFieldGroupRerender([...fldKeys, ...fdDefsKeys, ...collapsibleCheckHeaderKeys]); // force rerender on any change - - const rangeType= getVal('obsCoreWavelengthRangeType'); - const selectionType= getVal('obsCoreWavelengthSelectionType') ?? 'numerical'; - const hasFilters = filterDefinitions?.length > 0; - const useNumerical = !hasFilters || selectionType === 'numerical'; - const updatePanelStatus= makePanelStatusUpdater(checkHeaderCtl.isPanelActive(), panelValue); + const updatePanelStatus = makePanelStatusUpdater(checkHeaderCtl.isPanelActive(), panelValue); useEffect(() => { - const fldObj= makeFldObj([...fdDefsKeys, ...fldKeys]); - const constraints= makeWavelengthConstraints(selectionType,rangeType, filterDefinitions, fldObj); - updatePanelStatus(constraints, constraintResult, setConstraintResult,useSIAv2); + const fldObj = makeFldObj([...fdDefsKeys, ...fldKeys]); + const constraints = makeWavelengthConstraints(filterDefinitions, fldObj); + updatePanelStatus(constraints, constraintResult, setConstraintResult, useSIAv2); }); useEffect(() => { @@ -139,114 +290,23 @@ export function ObsCoreWavelengthSearch({initArgs, serviceLabel, slotProps,useSI return () => setConstraintFragment(panelPrefix, ''); }, [constraintResult]); - useFieldGroupWatch([...fdDefsKeys, - // 'obsCoreWavelengthContains', 'obsCoreWavelengthMinRange', 'obsCoreWavelengthMaxRange', 'obsCoreWavelengthUnits' ], - 'obsCoreWavelengthContains', 'obsCoreWavelengthMinRange', 'obsCoreWavelengthMaxRange' ], - (valAry,isInit) => { - !isInit && valAry.some((v)=>v) && checkHeaderCtl.setPanelActive(true); - }); - - const units= ( - - - - - ); - - + useFieldGroupWatch([...fdDefsKeys, obsCoreWvlFieldKeys.wvlContains, obsCoreWvlFieldKeys.wvlMin, obsCoreWvlFieldKeys.wvlMax], + (valAry, isInit) => { + !isInit && valAry.some((v) => v) && checkHeaderCtl.setPanelActive(true); + }); return ( - - + + - {hasFilters && } - {hasFilters && selectionType === 'filter' && - - Require coverage at the approximate center of these filters: - - {filterDefinitions.map((filterDefinition) => { - return ( - ); - })} - - - } - {useNumerical && - -
- -
- {rangeType === 'contains' && -
- -
- } - {rangeType === 'overlaps' && - - - to - - {units} - - } -
- } - + +
@@ -258,9 +318,7 @@ ObsCoreWavelengthSearch.propTypes = { serviceLabel: PropTypes.string, useSIAv2: PropTypes.bool, slotProps: PropTypes.shape({ - obsCoreWavelengthUnits: PropTypes.object, - obsCoreFilterDefinitions: PropTypes.object, - obsCoreWavelengthSelectionType: PropTypes.object, - obsCoreWavelengthRangeType: PropTypes.object, + root: PropTypes.object, + wavelengthOptions: WavelengthOptions.propTypes.slotProps }) };