UNPKG

terriajs

Version:

Geospatial data visualization platform.

146 lines 6.53 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import isEmpty from "lodash-es/isEmpty"; import { useEffect, useState } from "react"; import { useTranslation, withTranslation } from "react-i18next"; import ReactSelect from "react-select"; import styled from "styled-components"; import ErrorComponent from "./ErrorComponent"; import Loading from "./Loading"; import Text from "../../../Styled/Text"; import Box from "../../../Styled/Box"; import Button from "../../../Styled/Button"; const SearchForm = (props) => { const { parameters, itemSearchProvider } = props; const [t] = useTranslation(); const [state, setState] = useState({ is: "initial" }); const [query, setQuery] = useState(props.query); useEffect(function setValuesFromProps() { setQuery(props.query); }, [props.query]); const setParameterValue = (id, type) => (value) => { const newQuery = { ...query, [id]: { type, value } }; // Delete the value so that we don't trigger search for it if (newQuery[id].value === undefined) delete newQuery[id]; setQuery(newQuery); if (value !== undefined) props.onValueChange?.(id, value); }; function search() { const parameterValues = new Map(Object.entries(query).map(([id, { value }]) => [id, value])); setState({ is: "searching" }); itemSearchProvider .search(parameterValues) .then((results) => { setState({ is: "results", results }); props.onResults(query, results); }) .catch((error) => { console.warn(error); setState({ is: "error", error }); }); } const onSubmit = (e) => { try { search(); } finally { e.preventDefault(); } }; const clearForm = () => setQuery({}); const disabled = state.is === "searching"; return (_jsxs(Form, { onSubmit: onSubmit, children: [_jsxs(Box, { centered: true, children: [state.is === "searching" && (_jsx(Loading, { children: t("itemSearchTool.searching") })), state.is === "error" && (_jsx(ErrorComponent, { children: t("itemSearchTool.searchError") }))] }), _jsxs(FieldSet, { disabled: disabled, children: [parameters.map((p) => (_jsx(Field, { children: _jsx(Parameter, { parameter: p, onChange: setParameterValue(p.id, p.type), value: query[p.id]?.value, disabled: disabled, t: t }) }, p.id))), _jsx(SearchButton, { primary: true, type: "submit", disabled: disabled, children: t("itemSearchTool.searchBtnText") }), _jsx(Button, { secondary: true, type: "reset", onClick: clearForm, disabled: disabled, children: t("itemSearchTool.resetBtnText") })] })] })); }; const Parameter = (props) => { const { parameter } = props; switch (parameter.type) { case "numeric": return _jsx(NumericParameter, { ...props, parameter: parameter }); case "enum": return _jsx(EnumParameter, { ...props, parameter: parameter }); case "text": return _jsx(TextParameter, { ...props, parameter: parameter }); } }; export const NumericParameter = (props) => { const { parameter, value, t } = props; const { min, max } = parameter.range; const onChange = (tag) => (e) => { const parsed = parseFloat(e.target.value); const newValue = { ...props.value }; if (isNaN(parsed)) delete newValue[tag]; else newValue[tag] = parsed; props.onChange(isEmpty(newValue) ? undefined : newValue); }; return (_jsxs(Box, { column: true, children: [_jsx(ParameterName, { children: parameter.name }), _jsxs(Box, { css: ` justify-content: space-between; `, children: [_jsx(HalfWidthLabel, { children: _jsxs(Box, { column: true, children: [_jsx(Text, { small: true, children: t("itemSearchTool.numericParameter.minimum") }), _jsx(Input, { type: "number", name: `${parameter.id}-min`, value: value?.start ?? "", min: min, max: max, step: "any", placeholder: min.toString(), onChange: onChange("start") })] }) }), _jsx(HalfWidthLabel, { children: _jsxs(Box, { column: true, children: [_jsx(Text, { small: true, children: t("itemSearchTool.numericParameter.maximum") }), _jsx(Input, { type: "number", name: `${parameter.id}-max`, value: value?.end ?? "", min: min, max: max, step: "any", placeholder: max.toString(), onChange: onChange("end") })] }) })] })] })); }; const EnumParameter = (props) => { const { parameter, disabled } = props; const options = parameter.values.map(({ id }) => ({ value: id, label: id || "<empty>" })); const value = options.filter((o) => props.value?.includes(o.value)); const onChange = (selectedOptions) => { const values = selectedOptions?.map(({ value }) => value); props.onChange(values?.length === 0 ? undefined : values); }; return (_jsx(Box, { column: true, children: _jsxs(Label, { children: [_jsx(ParameterName, { children: parameter.name }), _jsx(Select, { name: parameter.id, options: options, isMulti: true, value: value, menuPosition: "fixed", onChange: onChange, isDisabled: disabled })] }) })); }; const TextParameter = (props) => { const { parameter, value, onChange } = props; return (_jsx(Box, { column: true, children: _jsxs(Label, { children: [_jsx(ParameterName, { children: parameter.name }), _jsx(Input, { type: "text", name: parameter.id, value: value || "", onChange: (e) => onChange(e.target.value ? e.target.value : undefined) })] }) })); }; const Form = styled.form ` width: 100%; `; export const FieldSet = styled.fieldset ` border: 0; margin: 0; padding: 0; min-width: 0; `; export const SearchButton = styled(Button) ` margin: 10px 10px 0 0; `; const Field = styled(Box).attrs({ column: true, paddedVertically: true }) ``; const ParameterName = styled(Text).attrs({ semiBold: true, breakWord: true }) ``; const Label = styled.label ``; const HalfWidthLabel = styled(Label) ` width: 45%; &:first-child { margin-right: 1em; } `; const Input = styled.input ` color: ${(p) => p.theme.dark}; box-sizing: border-box; width: 100%; height: 38px; font-size: 1.1em; `; const Select = styled((ReactSelect)).attrs({ classNamePrefix: "ReactSelect" }) ` color: ${(p) => p.theme.dark}; width: 100%; & .ReactSelect__control { border-radius: 0; } `; export default withTranslation()(SearchForm); //# sourceMappingURL=SearchForm.js.map