Skip to content
Open
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 component-library/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Input components (ValidationField, TargetPanel, etc.) stay in the core package b

Every app using the library must call `initFirefly()` once before rendering any store-connected component. It sets the Firefly server URL and bootstraps the Redux store. In Storybook it is called in `beforeAll` inside `.storybook/preview.jsx`.

Store-connected components (`ValidationField`, `TargetPanel`, `ListBoxInputField`, `SuggestBoxInputField`, etc.) use `useFieldGroupConnector` and require both `initFirefly()` to have run and a parent `FieldGroup` component to provide the group context.
Store-connected components (`ValidationField`, `TargetPanel`, `ListBoxInputField`, `AutoCompleteInput`, etc.) use `useFieldGroupConnector` and require both `initFirefly()` to have run and a parent `FieldGroup` component to provide the group context.

---

Expand Down
4 changes: 3 additions & 1 deletion component-library/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export { SwitchInputFieldView } from '../src/fir

// ─── Suggest / autocomplete ──────────────────────────────────────────────────

export { SuggestBoxInputField } from '../src/firefly/js/ui/SuggestBoxInputField.jsx';
export { AutoCompleteInput,
AutoCompleteInputView,
useAsyncOptions } from '../src/firefly/js/ui/AutoCompleteInput.jsx';

// ─── Target ──────────────────────────────────────────────────────────────────

Expand Down
80 changes: 0 additions & 80 deletions component-library/stories/inputs/SuggestBoxInputField.stories.jsx

This file was deleted.

38 changes: 28 additions & 10 deletions src/firefly/js/tables/ui/AddOrUpdateColumn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {dispatchTableFetch, dispatchTableUiUpdate} from '../TablesCntlr.js';
import {textValidator} from '../../util/Validate.js';
import {formatColExpr} from '../../charts/ChartUtil.js';
import {useStoreConnector} from '../../ui/SimpleComponent.jsx';
import {SuggestBoxInputField} from '../../ui/SuggestBoxInputField.jsx';
import {AutoCompleteInput} from '../../ui/AutoCompleteInput.jsx';

import MAGNIFYING_GLASS from 'images/icons-2014/magnifyingGlass.png';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
Expand Down Expand Up @@ -99,7 +99,6 @@ export const AddOrUpdateColumn = React.memo(({tbl_ui_id, tbl_id, hidePopup, edit
<Stack p={1} width={500} spacing={1} position='relative'
sx={{
'.ff-Input':{mb:1},
'.MuiInput-endDecorator > a':{width:12},
label:{width:80},
input:{width:265}
}}>
Expand Down Expand Up @@ -278,15 +277,16 @@ function CustomFields({tbl_ui_id, tbl_id, groupKey, editColName}) {
initialState={{value: col.units}}
tooltip='Units of measurement, IVOA VOUnits preferred'
/>
<SuggestBoxInputField fieldKey='ucd' label='UCD:'
<AutoCompleteInput fieldKey='ucd' label='UCD:'
slotProps={{
control:{orientation:'horizontal'},
tooltip: {placement: 'bottom'},
input:{endDecorator: <Info url='https://ivoa.net/documents/UCD1+'/>}
}}
endDecorator={<Info url='https://ivoa.net/documents/UCD1+'/>}
initialState={{value: col.UCD}}
tooltip='IVOA Unified Content Descriptor, UCD1+ style'
getSuggestions={getSuggestions} valueOnSuggestion={valueOnSuggestion}
options={UCDList}
filterOptions={ucdFilterOptions} onChange={onUcdSelect}
/>
<DescField desc={desc}/>
</>
Expand Down Expand Up @@ -344,10 +344,22 @@ const Samples = () => {
);
};

function getSuggestions(val) {
if (!val) return [];
const cvals = val.toLowerCase().split(';').map((v) => v.trim());
return UCDList.filter((ucd) => cvals.some((v) => ucd.includes(v)));
// a UCD1+ value is a ';'-delimited list, so this stays one text field rather than joy's `multiple`
// chips, which split on ',' and would drop any atom not in UCDList. Matching is unchanged from the
// pre-joy version: it tests every ';' token, not just the last one being typed.
function ucdFilterOptions(options, {inputValue}) {
// joy passes an empty inputValue on the render that opens the popup, so returning [] here would
// blank the listbox on the first keystroke
if (!inputValue) return options;
const cvals = inputValue.toLowerCase().split(';').map((v) => v.trim());
return options.filter(({value}) => cvals.some((v) => value.includes(v)));
}

// picking a suggestion replaces only the last ';'-segment; free-typed text is taken as-is
function onUcdSelect(ev, selected, reason, {value:cval, fireValueChange}) {
if (!selected) return fireValueChange({value: ''});
if (typeof selected === 'string') return fireValueChange({value: selected});
fireValueChange({value: valueOnSuggestion(cval, selected.value)});
}

function valueOnSuggestion(cval='', suggestion) {
Expand All @@ -358,6 +370,12 @@ function valueOnSuggestion(cval='', suggestion) {
return suggestion;
}

// width:12 is carried over from the panel's sx rule '.MuiInput-endDecorator > a', which no longer
// reaches this icon: on an Autocomplete joy names the slot .MuiAutocomplete-endDecorator, and
// AutoCompleteInput wraps decorators in a Stack. Setting it here covers both the Units and UCD icons.
function Info({url, target='info'}) {
return <Link href={url} target={target} tabIndex={-1} startDecorator={<InfoOutlinedIcon sx={{height: 16}}/>}/>;
return (
<Link href={url} target={target} tabIndex={-1} sx={{width: 12}}
startDecorator={<InfoOutlinedIcon sx={{height: 16}}/>}/>
);
}
21 changes: 2 additions & 19 deletions src/firefly/js/templates/lightcurve/LcUtil.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {getConverter} from './LcConverterFactory.js';
import {getCellValue, getTblById, findIndex, getColsByType, getColumnIdx, COL_TYPE} from '../../tables/TableUtil.js';
import {dispatchTableHighlight} from '../../tables/TablesCntlr.js';
import {ValidationField} from '../../ui/ValidationField.jsx';
import {SuggestBoxInputField} from '../../ui/SuggestBoxInputField.jsx';
import {AutoCompleteInput} from '../../ui/AutoCompleteInput.jsx';
import {getMissionName} from './LcConverterFactory.js';
import {getLayouInfo} from '../../core/LayoutCntlr.js';
import {getViewerGroupKey, onTimeColumnChange} from './LcManager.js';
Expand Down Expand Up @@ -87,21 +87,6 @@ export function keepHighlightedRowSynced(tbl_id, highlightedRow=0) {
});
}
}
/**
* @desc This method returns a suggested list of the column names based on the val entered and the defaultVal if provided.
* @param {string} val - the input in the text field
* @param {array} columnNames - the array of string
* @param {string} defaultVal - the default value, it can be null.
* @returns {*}
*/
export function getSuggestedList (val, columnNames, defaultVal) {
return columnNames.reduce((prev, name) => {
if ( name.startsWith(val) || (defaultVal && val===defaultVal)) {
prev.push(name);
}
return prev;
}, []);
}

export function getInitialDefaultValues(labelWidth, missionName) {
const commonDefault = {
Expand Down Expand Up @@ -173,13 +158,11 @@ export function getInitialDefaultValues(labelWidth, missionName) {
* @returns {Array}
*/
export function getMissionInput (numColumns){
const topZ = 3;
return (
<Stack {...{direction:'row', spacing:1/2, sx:{'& .ff-Input': {width:'8rem'}} }}>
{
[LC.META_TIME_CNAME, LC.META_FLUX_CNAME].map((key) =>
<SuggestBoxInputField key={key} fieldKey={key} popupIndex={topZ}
getSuggestions={(val) => getSuggestedList(val,numColumns)} />)
<AutoCompleteInput key={key} fieldKey={key} options={numColumns} orientation='vertical'/>)
}
</Stack>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import PropTypes from 'prop-types';
import {get, isEmpty} from 'lodash';
import {FieldGroup} from '../../../ui/FieldGroup.jsx';
import {ValidationField} from '../../../ui/ValidationField.jsx';
import {SuggestBoxInputField} from '../../../ui/SuggestBoxInputField.jsx';
import {AutoCompleteInput} from '../../../ui/AutoCompleteInput.jsx';
import {smartMerge} from '../../../tables/TableUtil.js';
import {makeFileRequest} from '../../../tables/TableRequestUtil.js';
import {ReadOnlyText,getSuggestedList,getInitialDefaultValues,getMissionInput,validate,fileUpdateOnTimeColumn,setValueAndValidator} from '../LcUtil.jsx';
import {ReadOnlyText,getInitialDefaultValues,getMissionInput,validate,fileUpdateOnTimeColumn,setValueAndValidator} from '../LcUtil.jsx';
import {LC, getViewerGroupKey} from '../LcManager.js';
import {getMissionName, coordSysOptions} from '../LcConverterFactory.js';
import {SettingBox} from '../SettingBox.jsx';

const labelWidth = 90;

const showAllOptions = (options) => options;

export class DefaultSettingBox extends SettingBox {
constructor(props) {
super(props);
Expand All @@ -30,12 +32,10 @@ export class DefaultSettingBox extends SettingBox {

const missionUrl = [LC.META_URL_CNAME];
const missionOtherKeys = [ LC.META_ERR_CNAME];
const topZ = 3;

const missionInputs=getMissionInput (numColumns, wrapperStyle);
const missionData = missionUrl.map((key) =>
(<SuggestBoxInputField key={key} fieldKey={key} popupIndex={topZ}
getSuggestions={(val) => getSuggestedList(val, charColumns)} />)
(<AutoCompleteInput key={key} fieldKey={key} options={charColumns} orientation='vertical'/>)
);

const missionOthers = missionOtherKeys.map((key) =>
Expand All @@ -46,12 +46,12 @@ export class DefaultSettingBox extends SettingBox {
const sKey = LC.META_COORD_SYS;

const sysCol = (
<SuggestBoxInputField key={sKey} fieldKey={sKey}
getSuggestions={() =>get(missionEntries, coordSysOptions, [])} />
<AutoCompleteInput key={sKey} fieldKey={sKey}
options={get(missionEntries, coordSysOptions, [])}
filterOptions={showAllOptions} orientation='vertical' />
);
const xyCols = [LC.META_COORD_XNAME, LC.META_COORD_YNAME].map((key) =>
(<SuggestBoxInputField key={key} fieldKey={key} popupIndex={topZ}
getSuggestions={(val) => getSuggestedList(val, charColumns)} />)
(<AutoCompleteInput key={key} fieldKey={key} options={charColumns} orientation='vertical'/>)
);

return [sysCol, xyCols];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import {get, isEmpty, set, pick, cloneDeep, defer} from 'lodash';
import {getLayouInfo} from '../../../core/LayoutCntlr.js';
import {ValidationField} from '../../../ui/ValidationField.jsx';
import {SuggestBoxInputField} from '../../../ui/SuggestBoxInputField.jsx';
import {AutoCompleteInput} from '../../../ui/AutoCompleteInput.jsx';
import {RadioGroupInputField} from '../../../ui/RadioGroupInputField.jsx';
import {FieldGroup} from '../../../ui/FieldGroup.jsx';
import {smartMerge} from '../../../tables/TableUtil.js';
Expand Down Expand Up @@ -42,15 +42,8 @@ export class LsstSdssSettingBox extends PureComponent {
const validFluxVals = get(missionEntries, LC.META_FLUX_NAMES, []);
const validTimeVals = get(missionEntries, LC.META_TIME_NAMES, []);

const suggestInput = (key, sugAry) => {
return (<SuggestBoxInputField key={key}
fieldKey={key} wrapperStyle={wrapperStyle}
getSuggestions={(val) => {
const suggestions = sugAry && sugAry.filter((el) => {return el.startsWith(val);});
return suggestions.length > 0 ? suggestions : sugAry;
}}
/>);
};
const suggestInput = (key, sugAry) =>
<AutoCompleteInput key={key} fieldKey={key} options={sugAry} orientation='vertical'/>;
var leftEntries = [
<RadioGroupInputField key='band' fieldKey='band' wrapperStyle={wrapperStyle}
alignment='horizontal'
Expand Down
Loading