import type { Correlation, Link } from 'nmr-correlation'; import { buildLink } from 'nmr-correlation'; import { useCallback, useMemo } from 'react'; import { buildID } from '../../../../data/utilities/Concatenation.js'; import { findRangeOrZoneID } from '../../../../data/utilities/FindUtilities.js'; import { ContextMenu } from '../../../elements/ContextMenuBluePrint.js'; import { useDialog } from '../../../elements/DialogManager.js'; import { useHighlight } from '../../../highlight/index.js'; import { cloneCorrelationAndEditLink, getAbbreviation, } from '../utilities/Utilities.js'; import useInView from '../utilities/useInView.js'; import type { EditLinkDialogData } from './editLink/EditLinkModal.js'; import { EditLinkModal } from './editLink/EditLinkModal.js'; function getLinkText(link: Link) { const { signal: { x, y }, edited, } = link; const deltaX = x?.delta?.toFixed(2) ?? '?'; const deltaY = y?.delta?.toFixed(2) ?? '?'; const movedLabel = edited?.moved ? '[MOVED]' : ''; return `${getAbbreviation(link)} (${deltaX} , ${deltaY}) ${movedLabel}`; } interface AdditionalColumnFieldProps { rowCorrelation: any; columnCorrelation: any; commonLinks: any; spectraData: any; onEdit: any; } function AdditionalColumnField(props: AdditionalColumnFieldProps) { const { rowCorrelation, columnCorrelation, commonLinks, spectraData, onEdit, } = props; const { openDialog } = useDialog(); const highlightIDsCommonLinks = useMemo(() => { return commonLinks.flatMap((link: Link) => { const ids: string[] = []; if (!link.pseudo) { ids.push(link.signal.id, buildID(link.signal.id, 'Crosshair')); const _id = findRangeOrZoneID( spectraData, link.experimentID, link.signal.id, true, ); if (_id) { ids.push(_id); } } return ids; }); }, [commonLinks, spectraData]); const highlightCommonLinks = useHighlight(highlightIDsCommonLinks); const mouseEnterHandler = useCallback( (event: any) => { event.currentTarget.focus(); highlightCommonLinks.show(); }, [highlightCommonLinks], ); const mouseLeaveHandler = useCallback( (event: any) => { event.currentTarget.blur(); highlightCommonLinks.hide(); }, [highlightCommonLinks], ); function contextMenuHandler(data: any) { highlightCommonLinks.hide(); openDialog(EditLinkModal, data); } const handleEditPseudoHSQC = useCallback( (action: 'add' | 'remove', link?: Link) => { const pseudoLinkCountHSQC = rowCorrelation.link.filter( (_link: any) => (_link.experimentType === 'hsqc' || _link.experimentType === 'hmqc') && _link.pseudo === true, ).length; let _correlationDim1: Correlation; let _correlationDim2: Correlation; if (action === 'add') { const commonPseudoLink = buildLink({ experimentType: 'hsqc', experimentID: crypto.randomUUID(), atomType: [columnCorrelation.atomType, rowCorrelation.atomType], id: crypto.randomUUID(), pseudo: true, signal: { id: crypto.randomUUID(), sign: 0 }, // pseudo signal }); _correlationDim1 = cloneCorrelationAndEditLink( columnCorrelation, commonPseudoLink, 'x', 'add', ); _correlationDim2 = cloneCorrelationAndEditLink( rowCorrelation, commonPseudoLink, 'y', 'add', ); // increase number of attached protons if no value was specified manually before if (!_correlationDim2.edited.protonsCount) { _correlationDim2.protonsCount = [pseudoLinkCountHSQC + 1]; } } else { _correlationDim1 = cloneCorrelationAndEditLink( columnCorrelation, link, 'x', 'remove', ); _correlationDim2 = cloneCorrelationAndEditLink( rowCorrelation, link, 'y', 'remove', ); // decrease number of attached protons if no value was specified manually before if (!_correlationDim2.edited.protonsCount) { _correlationDim2.protonsCount = pseudoLinkCountHSQC - 1 > 0 ? [pseudoLinkCountHSQC - 1] : []; } } onEdit([_correlationDim1, _correlationDim2], action, link, { skipDataUpdate: true, }); }, [columnCorrelation, onEdit, rowCorrelation], ); const contextMenu = useMemo(() => { // allow the edition of correlations const commonLinksMenu = commonLinks.flatMap((commonLink: any) => { if (commonLink.pseudo !== false) { return []; } return [ { text: `Edit ${getLinkText(commonLink)}`, icon: 'edit', data: { link: commonLink, correlationDim1: columnCorrelation, correlationDim2: rowCorrelation, }, }, ]; }); // allow addition or removal of a pseudo HSQC link between pseudo heavy atom and proton const commonPseudoLinkHSQC = commonLinks.find( (commonLink: any) => commonLink.pseudo === true && commonLink.experimentType === 'hsqc', ); if (rowCorrelation.pseudo === true) { if (commonPseudoLinkHSQC) { commonLinksMenu.push({ label: 'remove pseudo HSQC', onClick: () => handleEditPseudoHSQC('remove', commonPseudoLinkHSQC), }); } else { commonLinksMenu.push({ label: 'add pseudo HSQC', onClick: () => handleEditPseudoHSQC('add'), }); } } return commonLinksMenu; }, [columnCorrelation, commonLinks, handleEditPseudoHSQC, rowCorrelation]); const contentLabel = useMemo( () => commonLinks.map((commonLink: any, i: any) => ( )), [commonLinks], ); const isInViewRow = useInView({ correlation: rowCorrelation }); const isInViewColumn = useInView({ correlation: columnCorrelation }); return ( {contentLabel} ); } function getTitle(commonLinks: any) { if (commonLinks?.length === 0) { return ''; } return [ ...new Set( commonLinks?.link?.map((link: any) => { return link.experimentType.toUpperCase(); }), ), ].join('/'); } export default AdditionalColumnField;