Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/firefly/js/metaConvert/vo/ServDescConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,5 @@ export async function getServiceDescRelatedDataProduct(table, row, threeColorOps


export const findDataLinkServeDescs= (sdAry=[]) =>
sdAry?.filter( (serDef) => isDataLinkServiceDesc(serDef) ?? []);
sdAry?.filter( (serDef) => Boolean(isDataLinkServiceDesc(serDef)));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is Boolean needed? I think if anything, it may produces false positive.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for readability. the bug was the empty array.


6 changes: 3 additions & 3 deletions src/firefly/js/ui/tap/AdvancedADQL.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ export function AdvancedADQL({adqlKey, defAdqlKey, serviceUrl, capabilities, sty
let insertTname= tname;
if (upload) {
insertTname= TAP_UPLOAD_SCHEMA+'.'+tname;
const asTable= Object.values(uploadSchema).find( (o) => o.table===tname)?.asTable;
if (asTable) insertTname+= ' AS '+asTable;
const uploadTableAlias= Object.values(uploadSchema).find( (o) => o.table===tname)?.uploadTableAlias;
if (uploadTableAlias) insertTname+= ' AS '+uploadTableAlias;
}
setVal(adqlKey, `SELECT TOP 1000 * FROM ${maybeQuote(insertTname,true)}`);
window.setTimeout( () => prismLiveRef.current.syncStyles?.(), 10);
Expand Down Expand Up @@ -484,7 +484,7 @@ function expandColumns(serviceUrl, title, schema, uploadSchema, treeData, eventK
const schemaEntry=uploadSchema[tableKey];
if (!schemaEntry) return Promise.resolve();
const cols= schemaEntry.columns
.map( ({name}) => ( {key:makeColKey(key,schemaEntry.asTable?? schemaEntry.table,name),c: name, title:name, isLeaf:true}));
.map( ({name}) => ( {key:makeColKey(key,schemaEntry.uploadTableAlias?? schemaEntry.table,name),c: name, title:name, isLeaf:true}));
addChildNodes(treeData, eventKey, cols);
setTreeData(cloneDeep(treeData));
return Promise.resolve();
Expand Down
1 change: 1 addition & 0 deletions src/firefly/js/ui/tap/Constraints.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import {makeFullyQualifiedColumn} from './TapUtil';


export const ConstraintContext = React.createContext({});
Expand Down
28 changes: 17 additions & 11 deletions src/firefly/js/ui/tap/ObjectIDSearch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {useFieldGroupRerender, useFieldGroupValue, useFieldGroupWatch} from 'fir
import {
DebugObsCore, getPanelPrefix, makeCollapsibleCheckHeader, makeFieldErrorList, makePanelStatusUpdater
} from 'firefly/ui/tap/TableSearchHelpers';
import { ADQL_LINE_LENGTH, getAsEntryForTableName, makeUploadSchema, tapHelpId } from 'firefly/ui/tap/TapUtil';
import {
makeFullyQualifiedColumn, ADQL_LINE_LENGTH, getTableNameAlias, makeUploadSchema, tapHelpId
} from 'firefly/ui/tap/TapUtil';
import {bool,string,object} from 'prop-types';
import {ColsShape, getColValidator} from 'firefly/charts/ui/ColumnOrExpression';
import {CheckboxGroupInputField} from '../CheckboxGroupInputField.jsx';
Expand Down Expand Up @@ -53,7 +55,7 @@ export function ObjectIDSearch({cols, capabilities, tableName, columnsModel, use
const entryType= useFieldGroupValue(ENTRY_TYPE)[0]();
const objIdEntry= useFieldGroupValue(OBJ_ID_ENTRY)[0]();
const [working,setWorking]= useState(false);
const {setConstraintFragment}= useContext(ConstraintContext);
const {setConstraintFragment, doingUpload:anotherComponentUpload}= useContext(ConstraintContext);
const {canUpload=false}= capabilities ?? {};
const [openMsg, setOpenMsg]= useState(TAB_COLUMNS_MSG);
const {setVal,getVal,makeFldObj}= useContext(FieldGroupCtx);
Expand Down Expand Up @@ -114,7 +116,7 @@ export function ObjectIDSearch({cols, capabilities, tableName, columnsModel, use

useEffect(() => {
const constraints= makeObjectIDConstraints(makeFldObj(fldListAry), uploadInfo, tableName, canUpload,
getSelectInObjList(), getUseSelectIn()==='use', useSIAv2);
getSelectInObjList(), getUseSelectIn()==='use', anotherComponentUpload,useSIAv2);
updatePanelStatus(constraints, constraintResult, setConstraintResult,useSIAv2);
});

Expand All @@ -134,12 +136,12 @@ export function ObjectIDSearch({cols, capabilities, tableName, columnsModel, use
{!canUpload && !useSIAv2 && <Typography level='body-xs'>This search uses "Select IN" style SQL as this service does not support uploads.</Typography>}
<RadioGroupInputField {...{
fieldKey:ENTRY_TYPE, options:objIdEntryType, initialState:{value: 'enter'},
orientation:'horizontal', tooltip:`Enter object ID's as list or load from a table`,
orientation:'horizontal', tooltip:`Enter object ID's as list or load from a table`, // eslint-disable-line @stylistic/js/quotes
}} />

{entryType===ENTER ?
<InputAreaFieldConnected {...{ fieldKey:OBJ_ID_ENTRY, placeholderHighlight: true,
placeholder:`Enter one or more object id's separated by commas, semi-colon or space`,
placeholder:`Enter one or more object id's separated by commas, semi-colon or space`, // eslint-disable-line @stylistic/js/quotes
}}/> :
<UploadTableSelectorObjectID {...{uploadInfo,setUploadInfo, setSelectInObjList, getUseSelectIn, setWorking}}/>
}
Expand Down Expand Up @@ -238,7 +240,7 @@ function loadTableColumn(singleCol,serverFile,setSelectInObjList,setWorking) {
loadedColumns.set(serverFile + '---' + singleCol, list);
setSelectInObjList(list);
setWorking(false);
} catch (e) {
} catch (e) { // eslint-disable-line no-unused-vars
setWorking(false);
setSelectInObjList(undefined);
}
Expand All @@ -251,7 +253,8 @@ function loadTableColumn(singleCol,serverFile,setSelectInObjList,setWorking) {
}


function makeObjectIDConstraints(fldObj, uploadInfo, tableName, canUpload, selectInObjList, useSelectIn, useSIAv2) {
function makeObjectIDConstraints(fldObj, uploadInfo, tableName, canUpload, selectInObjList,
useSelectIn, anotherComponentUpload, useSIAv2) {
const {fileName,serverFile, columns:uploadColumns, totalRows, fileSize}= uploadInfo ?? {};
const { [UploadSingleColumn]:uploadObjectIDCol, [ObjectIDColumn]:objectIDCol, [ENTRY_TYPE]:entryType }= fldObj;
const errList= makeFieldErrorList();
Expand All @@ -270,22 +273,25 @@ function makeObjectIDConstraints(fldObj, uploadInfo, tableName, canUpload, selec
}
else if (!useSIAv2) {
if (!objectID) errList.addError('Selected Table (on the right) Object ID is not set');
else if (!selectInObjList?.length) errList.addError(`Object id's are not set`);
else if (!selectInObjList?.length) errList.addError(`Object id's are not set`); // eslint-disable-line @stylistic/js/quotes
}

if (useSelectIn || type===ENTER) {

const preFix= anotherComponentUpload ? getTableNameAlias(tableName) : '';
const objectIdCol= makeFullyQualifiedColumn(preFix,objectID);
if (selectInObjList?.length) {
const str= makeColsLines(selectInObjList);
adqlConstraint = `${objectID} IN (${str})`;
adqlConstraint = `${objectIdCol} IN (${str})`;
siaConstraints= selectInObjList.map( (id) => `ID=${encodeURIComponent(id)}`);
}
else {
errList.addError(`Enter at least one ${useSIAv2?'observation ID':'object ID'}`);
}
}
else if (!useSIAv2) {
const preFix= (serverFile && canUpload) ? `${getAsEntryForTableName(tableName)}` : '';
adqlConstraint = `(ut.${uploadedObjectID} = ${preFix}.${objectID})`;
const preFix= (serverFile && canUpload) ? getTableNameAlias(tableName) : '';
adqlConstraint = `(ut.${uploadedObjectID} = ${makeFullyQualifiedColumn(preFix,objectID)})`;
}

const errAry= errList.getErrors();
Expand Down
32 changes: 18 additions & 14 deletions src/firefly/js/ui/tap/ObsCore.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
makeFieldErrorList, getPanelPrefix, LableSaptail, makePanelStatusUpdater,
Width_Column, DebugObsCore, makeCollapsibleCheckHeader, SpatialWidth
} from 'firefly/ui/tap/TableSearchHelpers';
import {tapHelpId} from 'firefly/ui/tap/TapUtil';
import {getTableNameAlias, makeFullyQualifiedColumn, tapHelpId} from 'firefly/ui/tap/TapUtil';
import {ValidationField} from 'firefly/ui/ValidationField';
import PropTypes, {bool, string, object, shape, arrayOf} from 'prop-types';
import {FieldGroupCtx, ForceFieldGroupValid} from '../FieldGroup.jsx';
Expand All @@ -22,15 +22,16 @@ const panelValue = 'ObsCore';
const panelPrefix = getPanelPrefix(panelValue);


const multiConstraint = (value, columnName, siaName, quote, checkForNull) => {
const multiConstraint = (value, preFix, columnName, siaName, quote, checkForNull) => {
const multiConstraint = [];
const siaConstraints = [];
const valueList = value.split(',');
const col= makeFullyQualifiedColumn(preFix,columnName);
valueList.forEach((value) => {
if (checkForNull && value === 'null'){
multiConstraint.push(`${columnName} IS NULL`);
multiConstraint.push(`${col} IS NULL`);
} else {
multiConstraint.push(`${columnName} = ${quote}${value}${quote}`);
multiConstraint.push(`${col} = ${quote}${value}${quote}`);
}
siaConstraints.push(`${siaName}=${value}`);
});
Expand All @@ -44,9 +45,11 @@ const multiConstraint = (value, columnName, siaName, quote, checkForNull) => {
*
* @param hasSubType
* @param fldObj
* @param {boolean} doingUpload
* @param {string} tableName
* @returns {InputConstraints}
*/
const makeConstraints = function(hasSubType, fldObj) {
const makeConstraints = function(hasSubType, fldObj, doingUpload, tableName) {
const errList= makeFieldErrorList();
const adqlConstraintsAry = [];
const siaConstraints = [];
Expand All @@ -58,16 +61,17 @@ const makeConstraints = function(hasSubType, fldObj) {
obsCoreSubType, obsCoreInstrumentName, siaFacility}=fldObj;

// const {obsCoreCollection, obsCoreCalibrationLevel, obsCoreTypeSelection, obsCoreSubType, obsCoreInstrumentName} = fields;
const preFix= doingUpload ? getTableNameAlias(tableName) : '';
errList.checkForError(obsCoreCollection);
if (obsCoreCollection?.value?.length > 0) {
const mcResult = multiConstraint(obsCoreCollection.value, 'obs_collection', 'COLLECTION', '\'');
const mcResult = multiConstraint(obsCoreCollection.value, preFix, 'obs_collection', 'COLLECTION', '\'');
adqlConstraintsAry.push(mcResult.adqlConstraint);
siaConstraints.push(...mcResult.siaConstraints);
}

errList.checkForError(obsCoreCalibrationLevel);
if (obsCoreCalibrationLevel?.value) {
const mcResult = multiConstraint(obsCoreCalibrationLevel.value, 'calib_level', 'CALIB', '');
const mcResult = multiConstraint(obsCoreCalibrationLevel.value, preFix, 'calib_level', 'CALIB', '');
adqlConstraintsAry.push(mcResult.adqlConstraint);
siaConstraints.push(...mcResult.siaConstraints);
}
Expand All @@ -76,15 +80,15 @@ const makeConstraints = function(hasSubType, fldObj) {
if (siaFacility) {
errList.checkForError(siaFacility);
if (siaFacility?.value) {
const mcResult = multiConstraint(siaFacility.value, 'facility', 'FACILITY', '');
const mcResult = multiConstraint(siaFacility.value, preFix, 'facility', 'FACILITY', '');
adqlConstraintsAry.push(mcResult.adqlConstraint);
siaConstraints.push(...mcResult.siaConstraints);
}
}

errList.checkForError(obsCoreTypeSelection);
if (obsCoreTypeSelection?.value) {
const mcResult = multiConstraint(obsCoreTypeSelection.value, 'dataproduct_type', 'DPTYPE', '\'', true);
const mcResult = multiConstraint(obsCoreTypeSelection.value, preFix, 'dataproduct_type', 'DPTYPE', '\'', true);
adqlConstraintsAry.push(mcResult.adqlConstraint);

const siaErrorFields = ['visibility', 'event', 'null'];
Expand All @@ -95,7 +99,7 @@ const makeConstraints = function(hasSubType, fldObj) {

errList.checkForError(obsCoreInstrumentName);
if (obsCoreInstrumentName?.value?.length) {
const mcResult = multiConstraint(obsCoreInstrumentName.value, 'instrument_name', 'INSTRUMENT', '\'', true);
const mcResult = multiConstraint(obsCoreInstrumentName.value, preFix, 'instrument_name', 'INSTRUMENT', '\'', true);
adqlConstraintsAry.push(mcResult.adqlConstraint);
siaHasErrors(obsCoreInstrumentName.value, ['null'])
? siaConstraintErrors.push('null is not a valid SIA INSTRUMENT option')
Expand All @@ -105,7 +109,7 @@ const makeConstraints = function(hasSubType, fldObj) {
if (hasSubType){
errList.checkForError(obsCoreSubType);
if (obsCoreSubType?.value?.length > 0) {
const mcResult = multiConstraint(obsCoreSubType.value, 'dataproduct_subtype', 'DPSUBTYPE', '\'');
const mcResult = multiConstraint(obsCoreSubType.value, preFix, 'dataproduct_subtype', 'DPSUBTYPE', '\'');
adqlConstraintsAry.push(mcResult.adqlConstraint);
siaConstraints.push(...mcResult.siaConstraints);
}
Expand Down Expand Up @@ -162,11 +166,11 @@ const fldListAry= ['obsCoreCalibrationLevel', 'obsCoreTypeSelection', 'obsCoreSu

export function ObsCoreSearch({sx, cols, obsCoreMetadataModel, serviceId,
useCalibrationLevel=true, useProductType=true, useFacility=true,
useSubtype= true,
useSubtype= true, tableName,
useInstrumentName=true, useCollection=true,
initArgs={}, useSIAv2, slotProps={}}) {
const {urlApi={}}= initArgs;
const {setConstraintFragment}= useContext(ConstraintContext);
const {setConstraintFragment, doingUpload=false}= useContext(ConstraintContext);
const {makeFldObj}= useContext(FieldGroupCtx);
const obsCoreCollectionOptions = getDataServiceOption('obsCoreCollection',serviceId,{});
const obsCoreCalibrationLevelOptions = getDataServiceOption('obsCoreCalibrationLevel',serviceId,{});
Expand Down Expand Up @@ -204,7 +208,7 @@ export function ObsCoreSearch({sx, cols, obsCoreMetadataModel, serviceId,


useEffect(() => {
updatePanelStatus(makeConstraints(hasSubType,makeFldObj(fldListAry)), constraintResult, setConstraintResult,useSIAv2);
updatePanelStatus(makeConstraints(hasSubType,makeFldObj(fldListAry), doingUpload, tableName), constraintResult, setConstraintResult,useSIAv2);
});

useEffect(() => {
Expand Down
38 changes: 22 additions & 16 deletions src/firefly/js/ui/tap/ObsCoreExposureDuration.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Divider, FormControl, FormLabel, Stack, Typography} from '@mui/joy';
import PropTypes from 'prop-types';
import {bool, shape, string, object} from 'prop-types';
import React, {useContext, useEffect, useState} from 'react';
import Validate, {maximumPositiveFloatValidator, minimumPositiveFloatValidator} from '../../util/Validate.js';
import {FieldGroupCtx, ForceFieldGroupValid} from '../FieldGroup.jsx';
Expand All @@ -14,7 +14,7 @@ import {
makePanelStatusUpdater,
SmallFloatNumericWidth
} from './TableSearchHelpers.jsx';
import {tapHelpId} from './TapUtil.js';
import {getTableNameAlias, makeFullyQualifiedColumn, tapHelpId} from './TapUtil.js';

const START_EXP_GREATER_MSG= 'exposure time max must be greater than time min';
const ONE_POPULATED= 'at least one field must be populated';
Expand Down Expand Up @@ -60,7 +60,7 @@ function checkExposureDuration(expLenMin, expLenMax) {
* @param fldObj
* @returns {InputConstraints}
*/
function makeExposureConstraints(rangeType, fldObj) {
function makeExposureConstraints(rangeType, fldObj, doingUpload, tableName) {
const errList= makeFieldErrorList();
const siaConstraints= [];
const adqlConstraintsAry = [];
Expand All @@ -72,14 +72,18 @@ function makeExposureConstraints(rangeType, fldObj) {
const expLenMax = expLenMaxField?.value;

let seenValue = false;
const preFix= doingUpload ? getTableNameAlias(tableName) : '';
const tminCol= makeFullyQualifiedColumn(preFix,'t_min');
const tmaxCol= makeFullyQualifiedColumn(preFix,'t_max');
const tExpTimeCol= makeFullyQualifiedColumn(preFix,'t_exptime');
if (rangeType === 'range') {
if (exposureMin?.value || exposureMax?.value) {
const {minValue, maxValue}= checkExposureTime(exposureMin,exposureMax);
errList.checkForError(exposureMin);
errList.checkForError(exposureMax);
if (exposureMin?.valid && exposureMax?.valid) {
const rangeList = [[minValue, maxValue]];
adqlConstraintsAry.push(makeAdqlQueryRangeFragment('t_min', 't_max', rangeList, false));
adqlConstraintsAry.push(makeAdqlQueryRangeFragment(tminCol, tmaxCol, rangeList, false));
siaConstraints.push(...siaQueryRange('TIME', rangeList));
}
seenValue = true;
Expand All @@ -88,15 +92,15 @@ function makeExposureConstraints(rangeType, fldObj) {
errList.checkForError(expSince);
if (expSince?.valid) {
const rangeList = [[`${checkSinceTimeInMjd(expSince?.value, exposureSinceOptions?.value)}`, '+Inf']];
adqlConstraintsAry.push(makeAdqlQueryRangeFragment('t_min', 't_max', rangeList));
adqlConstraintsAry.push(makeAdqlQueryRangeFragment(tminCol, tmaxCol, rangeList));
siaConstraints.push(...siaQueryRange('TIME', rangeList));
}
seenValue = true;
}
if (expLenMin || expLenMax) {
const {rangeList, minGreaterThanMax}= checkExposureDuration(expLenMin,expLenMax);
if (!minGreaterThanMax) {
adqlConstraintsAry.push(makeAdqlQueryRangeFragment('t_exptime', 't_exptime', rangeList, true));
adqlConstraintsAry.push(makeAdqlQueryRangeFragment(tExpTimeCol, tExpTimeCol, rangeList, true));
siaConstraints.push(...siaQueryRange('EXPTIME', rangeList));
}
seenValue = true;
Expand All @@ -117,9 +121,9 @@ const {CollapsibleCheckHeader, collapsibleCheckHeaderKeys}= checkHeaderCtl;
const fldListAry= ['exposureSinceValue', 'exposureLengthMin', 'exposureLengthMax',
'exposureMin', 'exposureMax', 'exposureSinceOptions', 'exposureRangeType'];

export function ExposureDurationSearch({initArgs, slotProps,useSIAv2, showLengthInput=true}) {
export function ExposureDurationSearch({initArgs, slotProps,useSIAv2, showLengthInput=true, tableName}) {
const {getVal,makeFldObj}= useContext(FieldGroupCtx);
const {setConstraintFragment}= useContext(ConstraintContext);
const {setConstraintFragment, doingUpload=false}= useContext(ConstraintContext);
const [constraintResult, setConstraintResult] = useState({});
useFieldGroupRerender([...fldListAry, ...collapsibleCheckHeaderKeys] ); // force rerender on any change

Expand All @@ -129,7 +133,7 @@ export function ExposureDurationSearch({initArgs, slotProps,useSIAv2, showLength
const updatePanelStatus= makePanelStatusUpdater(checkHeaderCtl.isPanelActive(), panelValue);

useEffect(() => {
const constraints= makeExposureConstraints(getVal('exposureRangeType'), makeFldObj( fldListAry));
const constraints= makeExposureConstraints(getVal('exposureRangeType'), makeFldObj( fldListAry), doingUpload, tableName);
updatePanelStatus(constraints, constraintResult, setConstraintResult,useSIAv2);
});

Expand Down Expand Up @@ -169,14 +173,16 @@ export function ExposureDurationSearch({initArgs, slotProps,useSIAv2, showLength
}

ExposureDurationSearch.propTypes = {
initArgs: PropTypes.object,
useSIAv2: PropTypes.bool,
slotProps: PropTypes.shape({
exposureRangeType: PropTypes.object,
exposureTimeRange: PropTypes.object,
exposureSince: PropTypes.object,
initArgs: object,
useSIAv2: bool,
tableName: string,
slotProps: shape({
exposureRangeType: object,
exposureTimeRange: object,
exposureSince: object,
}),
showLengthInput: PropTypes.bool,
doingUpload: bool,
showLengthInput: bool,
};


Expand Down
Loading