diff --git a/src/component/elements/MolecularFormulaInput.tsx b/src/component/elements/MolecularFormulaInput.tsx deleted file mode 100644 index 402e0891bc..0000000000 --- a/src/component/elements/MolecularFormulaInput.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import { css } from '@emotion/react'; -import { useCallback, useState } from 'react'; - -import getAtomsFromMF from '../../data/utilities/getAtomsFromMF'; - -const inputStyle = css` - text-align: center; - - input { - height: 100%; - width: 200px; - border-radius: 5px; - border: 0.55px solid #c7c7c7; - margin: 0 5px; - text-align: center; - } - - button { - flex: 2; - padding: 5px; - border: 1px solid gray; - border-radius: 5px; - height: 36px; - margin: 0 auto; - margin-top: 15px; - display: block; - width: 20%; - color: white; - background-color: gray; - } -`; - -interface MolecularFormulaInputProps { - onSave?: (element: string) => void; - previousMF: string; -} - -function isValidMf(mf: string) { - if (mf.trim().length === 0) { - return false; - } - try { - getAtomsFromMF(mf); - return true; - } catch { - return false; - } -} - -export default function MolecularFormulaInput({ - onSave = () => null, - previousMF, -}: MolecularFormulaInputProps) { - const [mf, setMF] = useState(''); - const [isValidMF, setIsValidMF] = useState(true); - const [hasChanged, setHasChanged] = useState(false); - - const onChangeHandler = useCallback((e) => { - setHasChanged(true); - if (isValidMf(e.target.value)) { - setIsValidMF(true); - setMF(e.target.value); - } else { - setIsValidMF(false); - setMF(''); - } - }, []); - - const onSaveHandler = useCallback(() => { - onSave(hasChanged ? mf.trim() : previousMF); - }, [hasChanged, mf, onSave, previousMF]); - - return ( -
- - -
- ); -} diff --git a/src/component/elements/formik/FormikError.tsx b/src/component/elements/formik/FormikError.tsx index 0c0a21a9c5..c9dcddd8a2 100644 --- a/src/component/elements/formik/FormikError.tsx +++ b/src/component/elements/formik/FormikError.tsx @@ -4,7 +4,6 @@ import { CSSProperties, ReactNode } from 'react'; const styles: Record<'container' | 'text', CSSProperties> = { container: { - padding: '0.4rem', display: 'flex', flexDirection: 'column', }, @@ -22,15 +21,13 @@ export interface FormikErrorProps { } function FormikError({ style, name, children }: FormikErrorProps) { - const { errors, isValid, dirty, touched } = useFormikContext(); + const { errors, isValid, dirty } = useFormikContext(); const errorText = lodashGet(errors, name); - const isTouched = lodashGet(touched, name); - return (
{children} - {!isValid && dirty && isTouched && ( + {!isValid && dirty && ( {errorText} )}
diff --git a/src/component/elements/formik/FormikInput.tsx b/src/component/elements/formik/FormikInput.tsx index 9091cbec97..07d2f613b2 100644 --- a/src/component/elements/formik/FormikInput.tsx +++ b/src/component/elements/formik/FormikInput.tsx @@ -26,7 +26,7 @@ function FormikInput(props: FormikInputProps & InputProps) { ...resProps } = props; - const { values, handleChange, errors, touched, setFieldValue } = + const { values, handleChange, errors, touched, setFieldValue, handleBlur } = useFormikContext(); function changeHandler(e) { @@ -51,6 +51,7 @@ function FormikInput(props: FormikInputProps & InputProps) { name={name} value={val} onChange={changeHandler} + onBlur={handleBlur} type={type} style={{ ...style, diff --git a/src/component/panels/SummaryPanel/SetMolecularFormulaModal.tsx b/src/component/panels/SummaryPanel/SetMolecularFormulaModal.tsx index 372e359141..463a0a58ee 100644 --- a/src/component/panels/SummaryPanel/SetMolecularFormulaModal.tsx +++ b/src/component/panels/SummaryPanel/SetMolecularFormulaModal.tsx @@ -1,140 +1,185 @@ -/** @jsxImportSource @emotion/react */ -import { css } from '@emotion/react'; -import { useCallback, useEffect, useState } from 'react'; - -import { CloseButton } from '../../elements/CloseButton'; -import MolecularFormulaInput from '../../elements/MolecularFormulaInput'; +import { Dialog, DialogBody, Tab, Tabs } from '@blueprintjs/core'; +import { Formik } from 'formik'; +import { CSSProperties, useState } from 'react'; +import * as Yup from 'yup'; + +import getAtomsFromMF from '../../../data/utilities/getAtomsFromMF'; +import { useChartData } from '../../context/ChartContext'; +import { useDispatch } from '../../context/DispatchContext'; +import Button from '../../elements/Button'; import MoleculeSelection from '../../elements/MoleculeSelection'; - -const modalContainer = css` - overflow: auto; - width: 400px; - height: 550px; - padding: 5px; - - button { - flex: 2; - padding: 5px; - border: 1px solid gray; - border-radius: 5px; - height: 30px; - margin: 0 auto; - margin-top: 15px; - display: block; - width: 20%; - color: white; - background-color: gray; +import FormikError from '../../elements/formik/FormikError'; +import FormikInput from '../../elements/formik/FormikInput'; + +function isValidMf(value: string): boolean { + try { + getAtomsFromMF(value); + return true; + } catch { + return false; } +} - button:focus { - outline: none; - } +const validationSchema = Yup.object({ + mf: Yup.string() + .required() + .test('valid-mf', 'Enter a valid molecular formula', (value) => + isValidMf(value), + ), +}); + +const styles: Record<'container' | 'input' | 'error' | 'title', CSSProperties> = + { + input: { + padding: '0.5rem', + }, + container: { + padding: '0.5rem', + }, + error: { + textAlign: 'center', + color: 'red', + fontSize: '0.9em', + }, + title: { + textAlign: 'center', + }, + }; - .header { - height: 24px; - border-bottom: 1px solid #f0f0f0; - display: flex; - align-items: center; - - button { - height: 36px; - margin: 2px; - background-color: transparent; - border: none; - - svg { - height: 16px; - } - } - } +interface InnerMolecularFormulaModalProps { + onClose: () => void; +} +interface MolecularFormulaModalProps extends InnerMolecularFormulaModalProps { + isOpen: boolean; +} - .info { - margin-top: 0; - margin-bottom: 10px; - padding: 0 10px; - width: 100%; - text-align: center; - } +export function SetMolecularFormulaModal(props: MolecularFormulaModalProps) { + const { isOpen, ...otherProps } = props; - .optional { - margin-top: 20px; - margin-bottom: 5px; - padding: 0 10px; - text-align: center; - font-size: 18px; - font-weight: bold; + if (!isOpen) { + return; } - .optional2 { - margin-top: 5px; - margin-bottom: 25px; - padding: 0 10px; - width: 100%; - text-align: center; + return ; +} + +function InnerSetMolecularFormulaModal({ + onClose, +}: InnerMolecularFormulaModalProps) { + const dispatch = useDispatch(); + + function saveHandler(mf) { + dispatch({ + type: 'SET_CORRELATIONS_MF', + payload: { + mf, + }, + }); + onClose?.(); } -`; -interface SetMolecularFormulaModalProps { - onClose: () => void; - onSave?: (element: any) => void; - molecules: any; - previousMF: any; + return ( + + + + } + /> + } + /> + + + + ); } -export default function SetMolecularFormulaModal({ - onClose, - onSave, - molecules, - previousMF, -}: SetMolecularFormulaModalProps) { - const [currentIndex, setCurrentIndex] = useState(0); +function ManualFormula(props) { + const { correlations } = useChartData(); - useEffect(() => { - if (molecules && molecules.length > 0) { - setCurrentIndex(0); - } - }, [molecules]); + function saveHandler(data) { + props?.onSave(data.mf); + } - const onSaveHandlerMolecularFormulaInput = useCallback( - (mf) => { - onSave?.(mf); - onClose?.(); - }, - [onClose, onSave], + return ( +
+

Please type in a molecular formula!

+ + + {({ isValid, handleSubmit }) => ( + <> + + + + handleSubmit()} + disabled={!isValid} + style={{ marginTop: '10px' }} + > + Set molecular formula + + + )} + +
); +} - const onSaveHandlerMoleculeSelection = useCallback(() => { - onSave?.(molecules[currentIndex].mf); - onClose?.(); - }, [currentIndex, molecules, onClose, onSave]); +function AutoFormula(props) { + const { molecules } = useChartData(); + + const [currentIndex, setCurrentIndex] = useState(0); - const onChangeHandlerMoleculeSelection = useCallback((index) => { + function onChangeHandlerMoleculeSelection(index) { setCurrentIndex(index); - }, []); + } + + function saveHandler() { + const mf = molecules?.[currentIndex]?.mf; + props?.onSave(mf); + } + + if (!molecules || molecules?.length === 0) { + return ( +

+ You have to Select a spectrum and Add a molecule from the Structure + panel to select as a reference! +

+ ); + } return ( -
-
- -
-
-

Please type in a molecular formula!

-
- -
-

OR

-

Select a molecule as reference!

-
+
+

Select a molecule as reference!

- + + Set molecular formula +
); } diff --git a/src/component/panels/SummaryPanel/SummaryPanel.tsx b/src/component/panels/SummaryPanel/SummaryPanel.tsx index cc9b64686b..c1aa6e1928 100644 --- a/src/component/panels/SummaryPanel/SummaryPanel.tsx +++ b/src/component/panels/SummaryPanel/SummaryPanel.tsx @@ -23,13 +23,12 @@ import { useAssignmentData } from '../../assignment/AssignmentsContext'; import { useChartData } from '../../context/ChartContext'; import { useDispatch } from '../../context/DispatchContext'; import Select from '../../elements/Select'; -import { useModal } from '../../elements/popup/Modal'; import { useDialogToggle } from '../../hooks/useDialogToggle'; import DefaultPanelHeader from '../header/DefaultPanelHeader'; import CorrelationTable from './CorrelationTable/CorrelationTable'; import Overview from './Overview'; -import SetMolecularFormulaModal from './SetMolecularFormulaModal'; +import { SetMolecularFormulaModal } from './SetMolecularFormulaModal'; import { SetShiftToleranceModal } from './SetShiftTolerancesModal'; import { findSignalMatch1D, @@ -73,7 +72,6 @@ const panelStyle = css` function SummaryPanel() { const { - molecules, correlations: correlationsData, data: spectraData, xDomain, @@ -85,10 +83,10 @@ function SummaryPanel() { } = useChartData(); const dispatch = useDispatch(); - const modal = useModal(); const assignmentData = useAssignmentData(); const { dialog, openDialog, closeDialog } = useDialogToggle({ shiftToleranceModal: false, + molecularFormula: false, }); const [additionalColumnData, setAdditionalColumnData] = useState([]); @@ -230,39 +228,6 @@ function SummaryPanel() { yDomain, ]); - const handleOnSetMolecularFormula = useCallback( - (mf) => { - dispatch({ - type: 'SET_CORRELATIONS_MF', - payload: { - mf, - }, - }); - }, - [dispatch], - ); - - const showSetMolecularFormulaModal = useCallback(() => { - modal.show( - modal.close()} - onSave={handleOnSetMolecularFormula} - molecules={molecules} - previousMF={correlationsData.options.mf} - />, - ); - }, [correlationsData, handleOnSetMolecularFormula, modal, molecules]); - - // const showSetShiftToleranceModal = useCallback(() => { - // modal.show( - // modal.close()} - // onSavehandleOnSetShiftTolerance} - // previousTolerance={correlationsData.options.tolerance} - // />, - // ); - // }, [correlationsDatahandleOnSetShiftTolerance, modal]); - const additionalColumnTypes = useMemo(() => { const columnTypes = ['H', 'H-H'].concat( correlationsData @@ -487,6 +452,10 @@ function SummaryPanel() { const total = correlationsData ? correlationsData.values.length : 0; return (
+ , - title: `Set molecular formula (${correlationsData.options.mf})`, - onClick: showSetMolecularFormulaModal, + title: `Set molecular formula (${correlationsData?.options?.mf || ''})`, + onClick: () => openDialog('molecularFormula'), }, { icon: ,