Skip to content

Commit

Permalink
feat: live update the tree during edition
Browse files Browse the repository at this point in the history
close #1079
  • Loading branch information
hamed-musallam committed Jun 24, 2021
1 parent 9264f01 commit 2886523
Show file tree
Hide file tree
Showing 17 changed files with 335 additions and 211 deletions.
22 changes: 22 additions & 0 deletions src/component/1d/multiplicityTree/TempMultiplicityTree.tsx
@@ -0,0 +1,22 @@
import { memo } from 'react';

import TempRangeWrapper from '../../hoc/TempRangeWrapper';

import MultiplicityTree from './MultiplicityTree';

function TempMultiplicityTree({ range }) {
return (
range?.signal &&
range.signal.length > 0 &&
range.signal.map((signal) => (
<MultiplicityTree
rangeFrom={range.from}
rangeTo={range.to}
signal={signal}
key={signal.id}
/>
))
);
}

export default TempRangeWrapper(memo(TempMultiplicityTree));
4 changes: 2 additions & 2 deletions src/component/1d/multiplicityTree/buildTreeNode.ts
Expand Up @@ -24,10 +24,10 @@ function createTreeNodes(signal, spectrumData) {
const jIndex = jIndices.findIndex(
(_jIndex) => _jIndex === multiplicityIndex,
);

const frequency = lodashGet(spectrumData, 'info.originFrequency', 0);

const coupling =
jIndex >= 0 && frequency > 0
jIndex >= 0 && frequency > 0 && signal.j[jIndex]
? signal.j[jIndex].coupling / frequency // convert to ppm
: null;

Expand Down
36 changes: 24 additions & 12 deletions src/component/1d/ranges/Range.tsx
Expand Up @@ -13,6 +13,7 @@ import Resizable from '../Resizable';
import MultiplicityTree, {
SignalNodeProps,
} from '../multiplicityTree/MultiplicityTree';
import TempMultiplicityTree from '../multiplicityTree/TempMultiplicityTree';

const stylesOnHover = css`
pointer-events: bounding-box;
Expand Down Expand Up @@ -52,7 +53,7 @@ const stylesHighlighted = css`
`;

export interface RangeData {
id: number;
id: string;
from: number;
to: number;
integral: number;
Expand All @@ -63,9 +64,15 @@ interface RangeProps {
showMultiplicityTrees: boolean;
selectedTool: string;
rangeData: RangeData;
startEditMode: boolean;
}

function Range({ rangeData, showMultiplicityTrees, selectedTool }: RangeProps) {
function Range({
rangeData,
showMultiplicityTrees,
selectedTool,
startEditMode,
}: RangeProps) {
const { id, from: rangeFrom, to: rangeTo, integral, signal } = rangeData;
const assignmentRange = useAssignment(id);
const highlightRange = useHighlight(
Expand Down Expand Up @@ -194,16 +201,21 @@ function Range({ rangeData, showMultiplicityTrees, selectedTool }: RangeProps) {
onDrop={handleOnStopResizing}
onDrag={dragHandler}
/>
{showMultiplicityTrees && signal && signal.length > 0
? signal.map((_signal) => (
<MultiplicityTree
rangeFrom={from}
rangeTo={to}
signal={_signal}
key={_signal.id}
/>
))
: null}
{startEditMode ? (
<TempMultiplicityTree />
) : (
showMultiplicityTrees &&
signal &&
signal.length > 0 &&
signal.map((_signal) => (
<MultiplicityTree
rangeFrom={from}
rangeTo={to}
signal={_signal}
key={_signal.id}
/>
))
)}
</g>
);
}
Expand Down
9 changes: 8 additions & 1 deletion src/component/1d/ranges/Ranges.tsx
Expand Up @@ -11,9 +11,15 @@ interface RangesProps {
ranges: {
values: Array<RangeData>;
};
editRangeID: string;
}

function Ranges({ ranges, displayerKey, selectedTool }: RangesProps) {
function Ranges({
ranges,
displayerKey,
selectedTool,
editRangeID,
}: RangesProps) {
const [isMultiplicityTreesVisibile, showMultiplicityTrees] = useState(false);

useEffect(() => {
Expand All @@ -30,6 +36,7 @@ function Ranges({ ranges, displayerKey, selectedTool }: RangesProps) {
rangeData={range}
selectedTool={selectedTool}
showMultiplicityTrees={isMultiplicityTreesVisibile}
startEditMode={editRangeID && editRangeID === range.id ? true : false}
/>
))}
</g>
Expand Down
6 changes: 5 additions & 1 deletion src/component/hoc/RangesWrapper.jsx
Expand Up @@ -13,7 +13,10 @@ export default function RangesWrapper(WrappedComponent) {
molecules,
tabActiveSpectrum,
displayerKey,
toolOptions: { selectedTool },
toolOptions: {
selectedTool,
data: { tempRange },
},
} = useChartData();
const preferences = usePreferences();

Expand Down Expand Up @@ -57,6 +60,7 @@ export default function RangesWrapper(WrappedComponent) {
nucleus={nucleus}
displayerKey={displayerKey}
selectedTool={selectedTool}
editRangeID={tempRange?.id}
ref={forwardedRef}
/>
);
Expand Down
22 changes: 22 additions & 0 deletions src/component/hoc/TempRangeWrapper.jsx
@@ -0,0 +1,22 @@
import { memo, forwardRef } from 'react';

import { useChartData } from '../context/ChartContext';

export default function TempRangeWrapper(WrappedComponent) {
function Wrapper(props) {
const {
toolOptions: {
data: { tempRange },
},
} = useChartData();

const { forwardedRef, ...rest } = props;
return <WrappedComponent {...rest} range={tempRange} ref={forwardedRef} />;
}

return memo(
forwardRef((props, ref) => {
return <Wrapper {...props} forwardedRef={ref} />;
}),
);
}
2 changes: 1 addition & 1 deletion src/component/hooks/useToolsFunctions.js
Expand Up @@ -33,7 +33,7 @@ export default function useToolsFunctions() {
'Press Shift + Left Mouse button to select zone for integral and peak picking',
);
}
dispatch({ type: SET_SELECTED_TOOL, selectedTool });
dispatch({ type: SET_SELECTED_TOOL, payload: { selectedTool } });
},
[alert, dispatch],
);
Expand Down
119 changes: 55 additions & 64 deletions src/component/modal/editRange/EditRangeModal.jsx
@@ -1,22 +1,26 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import { Form, Formik } from 'formik';
import { useCallback, useEffect, useMemo } from 'react';
// import { Form, Formik } from 'formik';
import { useCallback, useEffect, useRef } from 'react';
import { FaSearchPlus } from 'react-icons/fa';

import generateID from '../../../data/utilities/generateID';
import { useChartData } from '../../context/ChartContext';
import { useDispatch } from '../../context/DispatchContext';
import Button from '../../elements/Button';
import CloseButton from '../../elements/CloseButton';
import SaveButton from '../../elements/SaveButton';
import FormikForm from '../../elements/formik/FormikForm';
import FormikOnChange from '../../elements/formik/FormikOnChange';
import {
hasCouplingConstant,
translateMultiplet,
} from '../../panels/extra/utilities/MultiplicityUtilities';
import { CHANGE_TEMP_RANGE } from '../../reducer/types/Types';
import { useFormatNumberByNucleus } from '../../utility/FormatNumber';

import SignalsForm from './forms/components/SignalsForm';
import EditRangeValidation from './forms/validation/EditRangeValidation';
import useRangeFormValidation from './forms/validation/EditRangeValidation';

const styles = css`
overflow: auto;
Expand Down Expand Up @@ -77,8 +81,11 @@ function EditRangeModal({
onZoomEditRangeModal,
rangeData,
}) {
const formRef = useRef();
const { activeTab } = useChartData();
const dispatch = useDispatch();
const format = useFormatNumberByNucleus(activeTab);
const validation = useRangeFormValidation();

const handleOnZoom = useCallback(() => {
onZoomEditRangeModal(rangeData);
Expand Down Expand Up @@ -131,8 +138,8 @@ function EditRangeModal({
[getSignals, handleOnClose, onSaveEditRangeModal, rangeData],
);

const initialStateSignals = useMemo(() => {
return rangeData.signal.map((_signal) => {
useEffect(() => {
const signals = rangeData.signal.map((_signal) => {
// counter within j array to access to right j values
let counterJ = 0;
const couplings = [];
Expand All @@ -151,68 +158,52 @@ function EditRangeModal({

return { ..._signal, j: couplings };
});
}, [format, rangeData.signal]);

const isSaveButtonDisabled = useCallback((errors) => {
const errorKeys = Object.keys(errors);
if (errorKeys.length > 0) {
if (
// ignore non-relevant newSignalDelta field
errorKeys.length === 1 &&
errorKeys[0] === 'newSignalDelta'
) {
return false;
}
return true;
}
return false;
}, []);
formRef.current.setValues({ activeTab: '0', signals });
}, [format, rangeData]);

const changeHandler = useCallback(
(values) => {
const { signals } = values;
const signal = getSignals(signals);
dispatch({
type: CHANGE_TEMP_RANGE,
payload: { tempRange: Object.assign({}, rangeData, { signal }) },
});
},
[dispatch, getSignals, rangeData],
);

return (
<div css={styles}>
{rangeData && (
<Formik
initialValues={{
signals: initialStateSignals,
newSignalDelta: (rangeData.from + rangeData.to) / 2,
activeTab: '0',
}}
validate={(values) => EditRangeValidation(values, rangeData)}
onSubmit={(values, { setSubmitting }) => {
handleOnSave(values);
setSubmitting(false);
}}
>
{({ values, errors }) => {
return (
<Form>
<div className="header handle">
<Button onClick={handleOnZoom} className="zoom-button">
<FaSearchPlus title="Set to default view on range in spectrum" />
</Button>
<span>
{` Range and Signal edition: ${format(
rangeData.from,
)} ppm to ${format(rangeData.to)} ppm`}
</span>
<SaveButton
onClick={() => handleOnSave(values)}
disabled={isSaveButtonDisabled(errors)}
popupTitle="Save and exit"
/>

<CloseButton onClick={handleOnClose} />
</div>
<SignalsForm
rangeLabel={`${format(rangeData.from)} ppm - ${format(
rangeData.to,
)} ppm`}
/>
</Form>
);
}}
</Formik>
)}
<FormikForm
ref={formRef}
initialValues={{
signals: [],
activeTab: '0',
}}
validationSchema={validation}
onSubmit={handleOnSave}
>
<div className="header handle">
<Button onClick={handleOnZoom} className="zoom-button">
<FaSearchPlus title="Set to default view on range in spectrum" />
</Button>
<span>
{` Range and Signal edition: ${format(
rangeData.from,
)} ppm to ${format(rangeData.to)} ppm`}
</span>
<SaveButton
onClick={() => formRef.current.submitForm()}
// disabled={formRef.current.errors}
popupTitle="Save and exit"
/>

<CloseButton onClick={handleOnClose} />
</div>
<SignalsForm rangeData={rangeData} format={format} />
<FormikOnChange onChange={changeHandler} />
</FormikForm>
</div>
);
}
Expand Down

0 comments on commit 2886523

Please sign in to comment.