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
4 changes: 3 additions & 1 deletion src/firefly/js/drawingLayers/HiPSMOC.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ function creator(initPayload) {
const preloadedTbl= tablePreloaded && getTblById(tbl_id);
drawingDef.color = preloadedTbl?.tableMeta?.[MetaConst.DEFAULT_COLOR] ?? defColors[mocGroupDefColorId] ?? color;
const defStyle= getAppOptions().hips.mocDefaultStyle ?? 'AUTO';
const inStyleStr= getMetaEntry(preloadedTbl, MetaConst.MOC_DEFAULT_STYLE, defStyle).toLowerCase();
const inStyleStr=
initPayload.mocStyle?.toLowerCase() ??
getMetaEntry(preloadedTbl, MetaConst.MOC_DEFAULT_STYLE, defStyle).toLowerCase();
switch (inStyleStr) {
case 'moc tile outline':
case 'tile outline':
Expand Down
10 changes: 3 additions & 7 deletions src/firefly/js/drawingLayers/HiPSMOCUI.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import {object} from 'prop-types';
import {RadioGroupInputFieldView} from '../ui/RadioGroupInputFieldView.jsx';
import {Style} from '../visualize/draw/DrawingDef.js';
import {dispatchModifyCustomField} from '../visualize/DrawLayerDispatch';
import {mocUIDisplayOptions} from '../visualize/HiPSMocUtil';


const options= [
{label: 'Outline', value: Style.DESTINATION_OUTLINE.key},
{label: 'Fill', value: Style.FILL.key},
{label: 'Auto', value: Style.AUTO.key},
{label: 'MOC Tile Outline', value: Style.STANDARD.key},
];


export const getUIComponent = (drawLayer,pv) => <HiPSMOCUI drawLayer={drawLayer} pv={pv}/>;
Expand All @@ -23,7 +19,7 @@ function HiPSMOCUI({drawLayer:dl,pv}) {
const style = dl?.requestedStyle ?? dl?.mocStyle?.[pv.plotId] ?? dl.drawingDef?.style ?? Style.DESTINATION_OUTLINE;

return (
<RadioGroupInputFieldView options={options} value={style.key}
<RadioGroupInputFieldView options={mocUIDisplayOptions} value={style.key}
buttonGroup={true}
onChange={(ev) => changeMocPref(dl,pv,ev.target.value, style.key)} />
);
Expand Down
3 changes: 2 additions & 1 deletion src/firefly/js/metaConvert/vo/ServDescProducts.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import {isEmpty, isNumber, isUndefined} from 'lodash';
import {getComponentState} from '../../core/ComponentCntlr.js';
import {getCellValue} from '../../tables/TableUtil.js';
import {CONTEXT_PARAMS_STR, makeCircleString} from '../../ui/dynamic/DynamicUISearchPanel';
import {hasAnySpacial, isSIAStandardID, sdToFieldDefAry} from '../../ui/dynamic/ServiceDefTools';
import {hasAnySpacial, sdToFieldDefAry} from '../../ui/dynamic/ServiceDefTools';
import {findCutoutTarget, getCutoutErrorStr, getCutoutSize, setCutoutSize} from '../../ui/tap/Cutout';
import {PlotAttribute} from '../../visualize/PlotAttribute';
import {isCatalog, isObsCoreLike} from '../../voAnalyzer/TableAnalysis';
import {CUTOUT_UCDs, DEC_UCDs, RA_UCDs} from '../../voAnalyzer/VoConst';
import {isSIAStandardID} from '../../voAnalyzer/VoCoreUtils';

import {findWorldPtInServiceDef, isDataLinkServiceDesc} from '../../voAnalyzer/VoDataLinkServDef.js';
import {isDefined} from '../../util/WebUtil.js';
Expand Down
2 changes: 1 addition & 1 deletion src/firefly/js/templates/common/ttFeatureWatchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import {useFieldGroupValue, useStoreConnector} from 'firefly/ui/SimpleComponent'
import {findCutoutTarget, getCutoutSize, ROW_POSITION, tblIdToKey,} from 'firefly/ui/tap/Cutout';
import {getTableModel} from 'firefly/voAnalyzer/VoCoreUtils';
import {fetchSemanticList} from 'firefly/metaConvert/vo/DatalinkFetch';
import {checkForDatalinkServDesc} from 'firefly/ui/dynamic/ServiceDefTools';
import {CheckboxGroupInputField, SelectAllCheckbox} from 'firefly/ui/CheckboxGroupInputField';
import {FormControl, FormLabel, Stack, Typography} from '@mui/joy';
import {ToolbarButton} from 'firefly/ui/ToolbarButton';
import {FieldGroup} from 'firefly/ui/FieldGroup';
import {getFieldVal} from 'firefly/fieldGroup/FieldGroupUtils';
import {makeFoVString} from 'firefly/visualize/ZoomUtil';
import {checkForDatalinkServDesc} from '../../voAnalyzer/VoDataLinkServDef';

export const getAllStartIds= ()=> [
getMocWatcherDef().id,
Expand Down
134 changes: 134 additions & 0 deletions src/firefly/js/ui/dynamic/CisxSerDescUtil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {isValidFullUrl} from '../../util/WebUtil';
import CoordinateSys from '../../visualize/CoordSys';
import {makeWorldPt} from '../../visualize/Point';


/*
* -------------------------------------
* Supports the processing of IRSA extension of service descriptor: <RESOURCE type="meta" utype="CISX:adhoc:service"
* -------------------------------------
*/



/**
* Pull the service descriptor (xml) moc related keys out and convert them to a form that can be later processed.
* The service descriptor might define multiple MOCs
* @param cisxUI
* @return {*} and object the defines multiple mocs that will be process by other parts of the application
*/

function findAndTranslateMocParameters(cisxUI) {
const translateMocXml = {
moc_color: 'mocColor',
moc_style: 'mocStyle',
moc_short_description: 'shortTitle',
};
const itemsList = Object.keys(translateMocXml);

const allMocsObj= cisxUI.filter(({name}) => {
if (!name) return false;
const key = name.toLowerCase();
return key === 'moc' || key.match(/moc\d+$/i) || itemsList.some((s) => key.startsWith(s));
})
.reduce((allMocs, {name, value, desc}) => {
const key = itemsList.find((k) => name.startsWith(k));
const id= name.substring(key?.length ?? 'moc'.length);
if (!allMocs[id]) allMocs[id] = {};
if (key) {
allMocs[id][translateMocXml[key]] = value;
} else {
allMocs[id].mocUrl= value;
allMocs[id].title= desc;
}
return allMocs;
}, {});
return Object.values(allMocsObj);
}

/**
*
* @param {Object} cisxUI
* @param {number} defaultMaxMOCFetchDepth
* @return {SearchAreaInfo}
*/
export function makeSearchAreaInfo(cisxUI, defaultMaxMOCFetchDepth) {
if (!cisxUI) return;
const tmpObj = cisxUI.reduce((obj, {name, value, UCD}) => {
switch (name) {
case 'hips_initial_fov':
obj[name] = Number(value);
break;
case 'hips_initial_dec':
case 'hips_initial_ra':
obj[name] = Number(value);
obj.ptIsGalactic = UCD?.includes('galactic');
break;
case 'polygon_examples':
case 'examples':
obj[name] = makeExamples(value);
break;
default:
if (!name?.startsWith('moc')) obj[name] = value;
break;
}
return obj;
}, {});

// const mocList= getMOCList(findAndTranslateMocParameters(cisxUI));
const mocList= findAndTranslateMocParameters(cisxUI);
const {hips_initial_ra, hips_initial_dec, hips_frame, ptIsGalactic} = tmpObj;
const hipsProjCsys = hips_frame?.trim().toLowerCase() === 'galactic' ? CoordinateSys.GALACTIC : CoordinateSys.EQ_J2000;
const ptCsys = ptIsGalactic ? CoordinateSys.GALACTIC : CoordinateSys.EQ_J2000;
const centerWp = makeWorldPt(hips_initial_ra, hips_initial_dec, ptCsys);
return {
...tmpObj, mocList, centerWp,
coordinateSys: hipsProjCsys.toString(), maxFetchDepth: defaultMaxMOCFetchDepth
};
}

function makeExamples(inExample) {
if (!inExample) return {targetPanelExampleRow1: undefined, targetPanelExampleRow2: undefined};
const examples = inExample.split('|');
if (examples?.length > 1) {
const cnt = examples.length;
return {
targetPanelExampleRow1: examples.slice(0, Math.trunc(cnt / 2)),
targetPanelExampleRow2: examples.slice(Math.trunc(cnt / 2))
};
} else {
return {targetPanelExampleRow1: [inExample], targetPanelExampleRow2: []};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This probably out of scope since it will change data structure everywhere else but instead of breaking examples to two rows we can let CSS handle that during rendering based on line wrapping.

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.

That could be really complex and often they want more control. It is something we could look at in the future.

}
}

/**
* @param {QueryAnalysis|ServiceDescriptorDef} qAnaOrSd - accept a QueryAnalysis or a ServiceDescriptorDef
* @return {CISXui|Array} ui parameters or an empty array
*/
export function getCisxUI(qAnaOrSd) {
if (!qAnaOrSd) return [];
if (qAnaOrSd.primarySearchDef) { // is QueryAnalysis
return qAnaOrSd.primarySearchDef[0]?.serviceDef?.cisxUI ?? [];
} else if (qAnaOrSd.accessURL) { // is ServiceDescriptorDef
return qAnaOrSd.cisxUI ?? [];
}
return [];
}

/**
* @param {QueryAnalysis|ServiceDescriptorDef} qAnaOrSd - accept a QueryAnalysis or a ServiceDescriptorDef
* @param {String} name
* @return the value
*/
export function getCisxUIValue(qAnaOrSd, name) {
return getCisxUI(qAnaOrSd).find((e) => e.name === name)?.value;
}

/**
* @param {QueryAnalysis|ServiceDescriptorDef} qAnaOrSd - accept a QueryAnalysis or a ServiceDescriptorDef
* @param {String} name
* @return the UCD
*/
export function getCisxUIUCD(qAnaOrSd, name) {
return getCisxUI(qAnaOrSd).find((e) => e.name === name)?.UCD;
}
107 changes: 78 additions & 29 deletions src/firefly/js/ui/dynamic/DLGenAnalyzeSearch.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import {isEmpty} from 'lodash';
import {isArray, isEmpty} from 'lodash';
import {MetaConst} from '../../data/MetaConst.js';
import {makeTblRequest} from '../../tables/TableRequestUtil';
import {sortInfoString} from '../../tables/SortInfo';
import {makeFileRequest, makeTblRequest, setNoCache} from '../../tables/TableRequestUtil';
import {dispatchTableSearch} from '../../tables/TablesCntlr.js';
import {getMetaEntry} from '../../tables/TableUtil.js';
import {Logger} from '../../util/Logger.js';
import {tokenSub} from '../../util/WebUtil';
import {CONE_CHOICE_KEY, POLY_CHOICE_KEY} from '../../visualize/ui/CommonUIKeys.js';
import {isCisxTapStandardID, isSIAStandardID, isSSAStandardID} from '../../voAnalyzer/VoCoreUtils';
import {getDataLinkData} from '../../voAnalyzer/VoDataLinkServDef.js';
import {getCisxUIValue} from './CisxSerDescUtil';
import {CIRCLE, POINT, POLYGON} from './DynamicDef.js';
import {
convertCircleToPointArea, convertPointAreaToCircle, isCircleSearch, isPointAreaSearch, isPolySearch
} from './DynamicUISearchPanel.jsx';
import {
findFieldDefType, isSIAStandardID, makeServiceDescriptorSearchRequest, sdToFieldDefAry
} from './ServiceDefTools.js';
import {findFieldDefType, sdToFieldDefAry} from './ServiceDefTools.js';


/**
Expand Down Expand Up @@ -47,7 +49,77 @@ export function analyzeQueries(tbl_id) {

let upTblCnt=1;

export function makeAllSearchRequest(request, siaConstraints, primeSd, concurrentSDAry, primaryFdAry, extraPrimaryMeta, uploadSiaExtParams) {
let tblCnt = 1;

function makeServiceDescriptorSearchRequest(request, siaConstraints = [], serviceDescriptor, extraMeta = {}) {
const {standardID = '', accessURL, utype, serDefParams, title, cisxUI = []} = serviceDescriptor;
const hiddenColumns = cisxUI.find((e) => e.name === 'hidden_columns')?.value;
const tblSortOrder = cisxUI.find((e) => e.name === 'table_sort_order')?.value;
const MAXREC = 50000;
const tblTitle = `${title} - ${tblCnt++}`;

const hideObj = hiddenColumns ?
Object.fromEntries(hiddenColumns.split(',').map((c) => [`col.${c}.visibility`, 'hide'])) : {};

const sAry = tblSortOrder?.match(/([^,]+),(.+)/);
let sortObj = {};
if (sAry) {
const [, dir, sortBy] = sAry;
sortObj = {sortInfo: sortInfoString(sortBy, dir?.toUpperCase() === 'ASC')};
}

const options = {...sortObj, META_INFO: {...hideObj, ...extraMeta}};
const requestAsArray = Object.entries(request).reduce((ary, [k, v]) => {
isArray(v)
? v.forEach((vEntry) => ary.push([k, vEntry]))
: ary.push([k, v]);
return ary;
}, []);

if (isSIAStandardID(standardID)) {
const reqParams = new URLSearchParams(requestAsArray);
const siaParams = new URLSearchParams();
siaConstraints.forEach((s) => {
const [k, v] = s.split('=');
if (k && v) siaParams.append(k, v);
});
const params = new URLSearchParams([...reqParams, ...siaParams]);
const url = params.size ? accessURL + '?' + params.toString() : accessURL;
return makeFileRequest(tblTitle, url, undefined, options); //todo- figure out title
} else if (isSSAStandardID(standardID)) {
const url = accessURL + '?' + new URLSearchParams(requestAsArray).toString();
return makeFileRequest(tblTitle, url, undefined, options); //todo- figure out title
} else if (isCisxTapStandardID(standardID, utype)) {
const doAsync = standardID.toLowerCase().includes('async');
const query = serDefParams.find(({name}) => name === 'QUERY')?.value;
const finalQuery = tokenSub(request, query);
let serviceUrl = accessURL;
if (accessURL.endsWith('/sync')) serviceUrl = accessURL.substring(0, accessURL.length - 5);
if (accessURL.endsWith('/async')) serviceUrl = accessURL.substring(0, accessURL.length - 6);

if (!query) return;
if (doAsync) {
const asyncReq = makeTblRequest('AsyncTapQuery', tblTitle, {
serviceUrl,
QUERY: finalQuery,
MAXREC
}, options);
setNoCache(asyncReq);
return asyncReq;
} else {
const serParam = new URLSearchParams({QUERY: finalQuery, REQUEST: 'doQuery', LANG: 'ADQL', MAXREC});
const completeUrl = serviceUrl + '/sync?' + serParam.toString();
return makeFileRequest(title, completeUrl, undefined, options); //todo- figure out title
}

} else {
//todo: we should to call file analysis first
const url = accessURL + '?' + new URLSearchParams(requestAsArray).toString();
return makeFileRequest(tblTitle, url, undefined, options); //todo- figure out title
}
}

function makeAllSearchRequest(request, siaConstraints, primeSd, concurrentSDAry, primaryFdAry, extraPrimaryMeta, uploadSiaExtParams) {
if (uploadSiaExtParams) {
const {title,accessURL} = primeSd;
const tblTitle= `${title} - upload ${upTblCnt++}`;
Expand Down Expand Up @@ -148,29 +220,6 @@ export function isSpatialTypeSupported(serviceDef, spacialType) {
*/


/**
* @param {QueryAnalysis|ServiceDescriptorDef} qAnaOrSd - accept a QueryAnalysis or a ServiceDescriptorDef
* @return {CISXui|Array} ui parameters or an empty array
*/
export function getCisxUI(qAnaOrSd) {
if (!qAnaOrSd) return [];
if (qAnaOrSd.primarySearchDef) { // is QueryAnalysis
return qAnaOrSd.primarySearchDef[0]?.serviceDef?.cisxUI ?? [];
} else if (qAnaOrSd.accessURL) { // is ServiceDescriptorDef
return qAnaOrSd.cisxUI ?? [];
}
return [];
}

export function getCisxUIValue(qAnaOrSd, name) {
return getCisxUI(qAnaOrSd).find((e) => e.name === name)?.value;
}

export function getCisxUIUCD(qAnaOrSd, name) {
return getCisxUI(qAnaOrSd).find((e) => e.name === name)?.UCD;
}


export function supportsUpload(qAna, standardID, useConcurrent= false) {
const hasUpload= getCisxUIValue(qAna,'IRSA_SIA_upload_extension') && isSIAStandardID(standardID);
if (!hasUpload) return false;
Expand Down
8 changes: 5 additions & 3 deletions src/firefly/js/ui/dynamic/DLGeneratedDropDown.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {FieldGroup} from '../FieldGroup.jsx';
import {showInfoPopup} from '../PopupUtil.jsx';
import {useStoreConnector} from '../SimpleComponent.jsx';
import {
analyzeQueries, getCisxUI, getCisxUIUCD, getCisxUIValue, handleSearch, supportsUpload
analyzeQueries, handleSearch, supportsUpload
} from './DLGenAnalyzeSearch.js';
import {SideBarAnimation, SideBarTable} from './DLuiDecoration.jsx';
import {DLuiServDescPanel, DLuiTabView} from './DLuiServDescPanel.jsx';
Expand All @@ -34,7 +34,9 @@ import {AREA, CIRCLE, CONE_AREA_KEY, POINT, POSITION, RANGE} from './DynamicDef.
import {convertRequest, DEFER_TO_CONTEXT, findTargetFromRequest} from './DynamicUISearchPanel.jsx';
import {getSpacialSearchType, hasValidSpacialSearch} from './DynComponents.jsx';
import {confirmDLMenuItem} from './FetchDatalinkTable.js';
import { getStandardIdType, ingestInitArgs, makeSearchAreaInfo, sdToFieldDefAry } from './ServiceDefTools.js';
import {getStandardIdType} from '../../voAnalyzer/VoCoreUtils';
import {getCisxUI, getCisxUIUCD, getCisxUIValue, makeSearchAreaInfo} from './CisxSerDescUtil';
import {ingestInitArgs, sdToFieldDefAry} from './ServiceDefTools.js';


export const DL_UI_LIST= 'DL_UI_LIST';
Expand Down Expand Up @@ -342,7 +344,7 @@ function DLGeneratedTableSearch({currentTblId, qAna, groupKey, initArgs, sideBar
alignHiPS(currentTblId,qAna,groupKey, fds);
}, [currentTblId, groupKey, qAna, searchObjFds, tabsKey]);

const isAllSky= toBoolean(getCisxUI(qAna)?.find( (e) => e.name==='data_covers_allsky')?.value);
const isAllSky= toBoolean(getCisxUIValue(qAna,'data_covers_allsky'));
const docRows= qAna?.urlRows.filter( ({semantic}) => semantic?.toLowerCase().endsWith('documentation'));

const submitSearch= (request,siaCtx) =>
Expand Down
4 changes: 2 additions & 2 deletions src/firefly/js/ui/dynamic/DLuiServDescPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import {Box, Link, Stack, Typography} from '@mui/joy';
import {array, arrayOf, bool, func, node, object, oneOfType, string} from 'prop-types';
import React, {useContext, useEffect, useState} from 'react';
import {CONE_CHOICE_KEY} from '../../visualize/ui/CommonUIKeys.js';
import {isSIAStandardID} from '../../voAnalyzer/VoCoreUtils';
import {CheckboxGroupInputField} from '../CheckboxGroupInputField.jsx';
import {FieldGroupCtx} from '../FieldGroup';
import {FieldGroupTabs, Tab} from '../panel/TabPanel';
import {showInfoPopup} from '../PopupUtil.jsx';
import {useFieldGroupValue} from '../SimpleComponent.jsx';
import {getServiceMetaOptions, loadSiaV2Meta, makeObsCoreMetadataModel} from '../tap/SiaUtil';
import {getCisxUIValue, hasSpatialTypes, isSpatialTypeSupported, supportsUpload} from './DLGenAnalyzeSearch.js';
import {hasSpatialTypes, isSpatialTypeSupported, supportsUpload} from './DLGenAnalyzeSearch.js';
import {DLSearchTitle} from './DLuiDecoration';
import {CONE_AREA_KEY} from './DynamicDef.js';
import {DynLayoutPanelTypes} from './DynamicUISearchPanel';
import {ConstraintContext} from '../tap/Constraints';
import {isSIAStandardID} from './ServiceDefTools';


const HIPS_PLOT_ID= 'dlGeneratedHipsPlotId';
Expand Down
Loading