Skip to content

Commit

Permalink
feat: improve zone assignment label addition and editing functionality (
Browse files Browse the repository at this point in the history
#3034)

* feat: improve zone assignment label addition and editing functionality

* refactor: display the add button when there are no assignment

* refactor: truncate the link angle value to one decimal

* refactor: apply 'bold' font weight to labels when the mouse is over the zone
  • Loading branch information
hamed-musallam committed May 3, 2024
1 parent c02ed38 commit d626f5e
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 37 deletions.
88 changes: 88 additions & 0 deletions src/component/1d-2d/FieldEdition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import { Popover, PopoverProps } from '@blueprintjs/core';

Check warning on line 3 in src/component/1d-2d/FieldEdition.tsx

View workflow job for this annotation

GitHub Actions / nodejs / lint-eslint

`@blueprintjs/core` import should occur before import of `@emotion/react`
import { Formik } from 'formik';
import { ReactNode, useState } from 'react';
import * as Yup from 'yup';

import FormikInput from '../elements/formik/FormikInput';

type InputType = 'number' | 'text';

interface FieldEditionsProps {
value: number | string;
inputType?: InputType;
onChange: (value: any) => void;
children: ReactNode;
PopoverProps?: PopoverProps;
}
const InputDimension = { height: 28, width: 100 };

const validationSchema = (inputType: 'number' | 'text') =>
Yup.object({
value: (inputType === 'number' ? Yup.number() : Yup.string()).required(),
});

function stopPropagation(e) {
e.stopPropagation();
}

function keyDownCheck(event: React.KeyboardEvent<HTMLInputElement>) {
if (event.key === 'Enter') {
return true;
} else if (event.key === 'Escape') {
return false;
}
}

export function FieldEdition(props: FieldEditionsProps) {
const { value, inputType = 'text', onChange, children, PopoverProps } = props;
const [isOpen, setIsOpen] = useState(false);

function handleOnSubmit({ value: newValue }) {
onChange(newValue);
setIsOpen(false);
}

return (
<Popover
css={css`
.field-edition-popover {
border-radius: 5px;
}
`}
popoverClassName="field-edition-popover"
isOpen={isOpen}
onClose={() => setIsOpen(false)}
onInteraction={() => setIsOpen(true)}
content={
<Formik
initialValues={{ value }}
onSubmit={handleOnSubmit}
validationSchema={validationSchema(inputType)}
>
{({ submitForm }) => (
<FormikInput
type={inputType}
style={{
input: {
height: `${InputDimension.height}px`,
padding: '5px',
outline: 'none',
},
}}
name="value"
autoSelect
onKeyDown={(e) => keyDownCheck(e) && submitForm()}
onClick={stopPropagation}
onMouseDown={stopPropagation}
/>
)}
</Formik>
}
{...PopoverProps}
>
{children}
</Popover>
);
}
11 changes: 7 additions & 4 deletions src/component/2d/Chart2D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FTContainer } from './ft/FTContainer';
import IndicationLines from './zones/IndicationLines';
import Zones from './zones/Zones';
import ZonesAssignmentsLabels from './zones/ZonesAssignmentsLabels';

Check warning on line 15 in src/component/2d/Chart2D.tsx

View workflow job for this annotation

GitHub Actions / nodejs / lint-eslint

There should be at least one empty line between import groups
import { ShareDataProvider } from '../context/ShareDataContext';

Check warning on line 16 in src/component/2d/Chart2D.tsx

View workflow job for this annotation

GitHub Actions / nodejs / lint-eslint

`../context/ShareDataContext` import should occur before import of `../reducer/Reducer`

interface Chart2DProps {
spectra?: Spectrum1D[];
Expand All @@ -26,7 +27,7 @@ interface Chart2DInnerProps extends Chart2DProps {
spectraRendering: SpectraRendering;
}

function chart2DInner({
function Chart2DInner({
spectra,
width,
height,
Expand Down Expand Up @@ -67,8 +68,10 @@ function chart2DInner({
/>
<FTContainer spectra={spectra} />
<FidContainer />
<Zones />
<ZonesAssignmentsLabels />
<ShareDataProvider>
<Zones />
<ZonesAssignmentsLabels />
</ShareDataProvider>
<IndicationLines axis="X" show />
<IndicationLines axis="Y" show />
<SpectrumInfoBlock />
Expand All @@ -80,7 +83,7 @@ function chart2DInner({
);
}

const MemoizedChart2D = memo(chart2DInner);
const MemoizedChart2D = memo(Chart2DInner);

export default function Chart2D({ spectra }: Chart2DProps) {
const { width, height, margin, displayerKey } = useChartData();
Expand Down
37 changes: 34 additions & 3 deletions src/component/2d/zones/Zone.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { Zone as ZoneType } from 'nmr-processing';
import { useState, useEffect } from 'react';

import { checkZoneKind } from '../../../data/utilities/ZoneUtilities';
import { useAssignment } from '../../assignment/AssignmentsContext';
import { useShareData } from '../../context/ShareDataContext';
import { SVGButton } from '../../elements/SVGButton';
import { HighlightEventSource, useHighlight } from '../../highlight';
import { useActiveSpectrumZonesViewState } from '../../hooks/useActiveSpectrumZonesViewState';
import { useScale2DX, useScale2DY } from '../utilities/scale';
Expand Down Expand Up @@ -42,12 +45,25 @@ const stylesHighlighted = css`
}
`;

const GroupContainer = styled.g`
.target {
visibility: hidden;
}
&:hover {
.target {
visibility: visible;
}
}
`;

interface ZoneProps {
zoneData: ZoneType;
}

function Zone({ zoneData }: ZoneProps) {
const { x, y, id, signals } = zoneData;
const { x, y, id, signals, assignment } = zoneData;
const { setData } = useShareData<{ id: string }>();
const assignmentZone = useAssignment(id);
const { showZones } = useActiveSpectrumZonesViewState();
const highlightZone = useHighlight([assignmentZone.id], {
Expand Down Expand Up @@ -84,7 +100,22 @@ function Zone({ zoneData }: ZoneProps) {
}}
>
{showZones && (
<g transform={`translate(${scaleX(x2)},${scaleY(y1)})`}>
<GroupContainer transform={`translate(${scaleX(x2)},${scaleY(y1)})`}>
<g
data-no-export="true"
transform="translate(-16 -16)"
className="target"
>
{!assignment && (
<SVGButton
icon="plus"
backgroundColor="green"
title="Add assignment label"
style={{ cursor: 'hand' }}
onClick={() => setData({ id })}
/>
)}
</g>
<rect
x="0"
width={scaleX(x1) - scaleX(x2)}
Expand All @@ -94,7 +125,7 @@ function Zone({ zoneData }: ZoneProps) {
stroke={reduceOpacity ? '#343a40' : 'darkgreen'}
strokeWidth={reduceOpacity ? '0' : '1'}
/>
</g>
</GroupContainer>
)}
{signals.map((_signal, i) => (
<Signal key={String(id + i)} signal={_signal} />
Expand Down
Loading

0 comments on commit d626f5e

Please sign in to comment.