diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/VosiCapabilityRetrieve.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/VosiCapabilityRetrieve.java index f6923a1102..80bbc1641c 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/VosiCapabilityRetrieve.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/VosiCapabilityRetrieve.java @@ -17,7 +17,10 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Stack; /** @@ -78,15 +81,17 @@ static class CapabilityHandle extends DefaultHandler { private boolean canUseCoord2= false; private boolean canUseCoordSys= false; private boolean canUseDistance= false; + private final List outputFormats = new ArrayList<>(); boolean foundTAP= false; boolean foundFeatures= false; + boolean foundOutputFormat= false; boolean geoFeaturesProcess = false; CapabilityHandle() { } public TapCapability getTapCapability() { if (geoFeaturesProcess) { - return new TapCapability( canUpload, true, + return new TapCapability(outputFormats, canUpload, true, canUsePoint, canUseCircle, canUseBox, canUsePolygon, canUseRegion, canUseContains, canUseIntersects, canUseArea, canUseCentroid, @@ -110,6 +115,9 @@ public void startElement(String uri, String localName, String qName, Attributes if (qName.equals("uploadMethod") && confirmAttribute(att,"ivo-id", uploadHttp)) { canUpload= true; } + if (qName.equals("outputFormat")) { + foundOutputFormat= true; + } } currValue.setLength(0); currElement.push(qName); @@ -119,8 +127,7 @@ public void startElement(String uri, String localName, String qName, Attributes public void endElement(String uri, String localName, String qName) { if (foundTAP && qName.equals("capability")) foundTAP= false; if (foundFeatures && qName.equals("languageFeatures")) foundFeatures= false; - - + if (foundOutputFormat && qName.equals("outputFormat")) foundOutputFormat= false; String value= currValue.toString(); @@ -142,6 +149,9 @@ public void endElement(String uri, String localName, String qName) { } geoFeaturesProcess = true; } + if (foundTAP && foundOutputFormat && qName.equals("mime")) { + outputFormats.add(value); + } if (!currElement.empty()) currElement.pop(); } @@ -165,15 +175,19 @@ private static boolean confirmAttribute(Attributes att, String attName, String[] public record Capabilities( TapCapability tapCapability) {} - public record TapCapability( boolean canUpload, boolean foundGeoLanguageFeatures, - boolean canUsePoint, boolean canUseCircle, boolean canUseBox, - boolean canUsePolygon, boolean canUseRegion, boolean canUseContains, - boolean canUseIntersects, boolean canUseArea, boolean canUseCentroid, - boolean canUseCoord1, boolean canUseCoord2, boolean canUseCoordSys, - boolean canUseDistance) {} + public record TapCapability( + List outputFormats, + boolean canUpload, boolean foundGeoLanguageFeatures, + boolean canUsePoint, boolean canUseCircle, boolean canUseBox, + boolean canUsePolygon, boolean canUseRegion, boolean canUseContains, + boolean canUseIntersects, boolean canUseArea, boolean canUseCentroid, + boolean canUseCoord1, boolean canUseCoord2, boolean canUseCoordSys, + boolean canUseDistance) {} private static TapCapability makeDefaultTapCapability(boolean canUpload) { - return new TapCapability(canUpload, false, + return new TapCapability( + Collections.emptyList(), + canUpload, false, true,true,false, true,false,true, false,false,false, diff --git a/src/firefly/js/fieldGroup/FieldGroupCntlr.js b/src/firefly/js/fieldGroup/FieldGroupCntlr.js index 6992eb0b60..e28a357440 100644 --- a/src/firefly/js/fieldGroup/FieldGroupCntlr.js +++ b/src/firefly/js/fieldGroup/FieldGroupCntlr.js @@ -121,8 +121,8 @@ export function dispatchMountComponent(groupKey,fieldKey,mounted,value,initField * @param {Object} payload * @param {String} payload.fieldKey the field Key * @param {String} payload.groupKey group key - * @param {String} payload.value value can be anything including a promise or function - * @param {boolean} payload.valid - true if valid, default to true + * @param {String} [payload.value] value can be anything including a promise or function + * @param {boolean} [payload.valid] - true if valid, default to true */ export function dispatchValueChange(payload) { flux.process({type: VALUE_CHANGE, payload}); diff --git a/src/firefly/js/ui/FieldGroupConnector.jsx b/src/firefly/js/ui/FieldGroupConnector.jsx index 722257f5d1..739161730f 100644 --- a/src/firefly/js/ui/FieldGroupConnector.jsx +++ b/src/firefly/js/ui/FieldGroupConnector.jsx @@ -20,7 +20,7 @@ const STORE_OMIT_LIST= ['fieldKey', 'groupKey', 'initialState', 'fireReducer', 'confirmValue', 'confirmValueOnInit', 'forceReinit', 'mounted']; function buildViewProps(fieldState,props,fieldKey,groupKey,value='') { - const {message= '', valid= true, visible= true, value:ignoreValue, displayValue= '', + const {message= '', valid= true, visible= true, displayValue= '', tooltip= '', validator= defValidatorFunc, ...rest}= fieldState; const propsClean= Object.keys(props).reduce( (obj,k)=> { if (isDefined(props[k]) && k!=='value') obj[k]=props[k]; @@ -57,12 +57,22 @@ function hasNewKeys(infoRef,fieldKey,groupKey) { return isInit(infoRef,fieldKey,groupKey) && prevFieldKey && prevGroupKey; } +/** + * @param {String} groupKey + * @param {Object} initialState + * @param {Object} props + * @param {ConfirmValueFunc} confirmValueOnInit + * @return {Object} + */ function doGetInitialState(groupKey, initialState, props, confirmValueOnInit= defaultConfirmValue) { const {fieldKey}= props; const {keepState=false}= getFieldGroupState(groupKey) ?? {}; - const storeField= get(FieldGroupUtils.getGroupFields(groupKey), [fieldKey]); - const initS= !keepState ? (initialState || storeField || {}) : (storeField || initialState || {}); - return {...initS, value: confirmValueOnInit(initS.value,props,initialState,initS)}; + const storeField= FieldGroupUtils.getGroupFields(groupKey)[fieldKey] ?? {}; + const computedState= keepState + ? {...initialState, ...storeField} + : (initialState ?? storeField); + const value= confirmValueOnInit(computedState.value,props,initialState,computedState); + return {...computedState, value}; } @@ -102,13 +112,6 @@ export const fgConnectPropsTypes= { confirmValue: PropTypes.func }; -/** - * Minimal set of properties ot use for useFieldGroupConnector - */ -export const fgMinPropTypes= { - fieldKey: PropTypes.string.isRequired, - groupKey: PropTypes.string, // normally passed in context -}; /** * @name ConfirmValueFunc @@ -118,6 +121,7 @@ export const fgMinPropTypes= { * @param {*} value * @param {Object} props * @param {Object} state + * @param {Object|undefined} computedState * @returns * */ @@ -160,16 +164,13 @@ export const useFieldGroupConnector= (props) => { } } - const getInitialState= () => doGetInitialState(groupKey, initialState, props, (confirmValueOnInit||confirmValue)); + const getInitialState= () => doGetInitialState(groupKey, initialState, props, (confirmValueOnInit ?? confirmValue)); const [fieldState, setFieldState] = useState(() => getInitialState()); const fireValueChange= (payload) => dispatchValueChange({...payload, fieldKey,groupKey}); const value= confirmValue ? confirmValue(fieldState.value,props,fieldState) : fieldState.value; - const effectChangeAry= [fieldKey, groupKey, fieldState]; - if (confirmValue) effectChangeAry.push(value); // only need to watch value in this case - useEffect(() => { if (doingInit) { // called the first time or when fieldKey or groupKey change @@ -205,11 +206,11 @@ export const useFieldGroupConnector= (props) => { if (!gState || !gState.mounted || !get(gState,['fields',fieldKey])) return; if (fieldState !== gState.fields[fieldKey]) setFieldState(gState.fields[fieldKey]); }); - }, effectChangeAry); + }, [fieldKey, groupKey, fieldState,confirmValue]); useEffect(() => { // only run on dismount return () => dispatchMountComponent( groupKey, fieldKey, false); - }, []); + }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { if (doingInit || isUndefined(forceValid)) return; @@ -221,7 +222,7 @@ export const useFieldGroupConnector= (props) => { f.validator= f.validator ?? props.validator; if (canValidate(f)) fireValueChange({...callValidator(f)}); } - }, [forceValid]); + }, [forceValid]); // eslint-disable-line react-hooks/exhaustive-deps return { fireValueChange, viewProps: buildViewProps(fieldState,props,fieldKey,groupKey, value), fieldKey, groupKey diff --git a/src/firefly/js/ui/QuantityInputField.jsx b/src/firefly/js/ui/QuantityInputField.jsx index 6cd4de0487..c4e1a70353 100644 --- a/src/firefly/js/ui/QuantityInputField.jsx +++ b/src/firefly/js/ui/QuantityInputField.jsx @@ -211,10 +211,7 @@ export const QuantityInputField = memo((props) => { }); useEffect(() => { - if (!viewProps?.unit && initUnit) { - // if unit is missing from store, set it from initialState - fireValueChange({unit: initUnit}); - } else if ((viewProps?.value || viewProps?.value===0) && viewProps?.unit && !viewProps?.displayValue) { + if ((viewProps?.value || viewProps?.value===0) && viewProps?.unit && !viewProps?.displayValue) { // if value changed in the store (for e.g. by a setFieldValue()) and there's no displayValue, set it const newDisplayValue = convertQuantityUnits(viewProps.value, quantityBaseUnit, viewProps.unit); fireValueChange({displayValue: newDisplayValue});