From fbbd70c966bc8414a45f0cd856827d452f579cc6 Mon Sep 17 00:00:00 2001 From: Ilya Asiyuk Date: Thu, 16 May 2024 17:23:12 +0400 Subject: [PATCH] #4501 - Macro: The system allows you to paste on canvas while modifying nucleotides in the RNA builder --- .../src/application/editor/Editor.ts | 11 ++++- .../src/application/editor/modes/BaseMode.ts | 6 ++- .../editor/tools/SelectRectangle.ts | 9 +--- .../ketcher-core/src/application/ketcher.ts | 19 ++------ .../sequence/BaseSequenceItemRenderer.ts | 11 +---- .../renderers/sequence/SequenceRenderer.ts | 5 +- .../ketcher-macromolecules/src/Editor.tsx | 13 ++--- .../LayoutModeButton/LayoutModeButton.tsx | 8 +--- .../SequenceTypeDropdown.tsx | 8 +--- .../components/contextMenu/RNAContextMenu.tsx | 10 ++-- .../SequenceItemContextMenu.tsx | 8 +--- .../monomerLibrary/MonomerLibrary.tsx | 15 +++--- .../RnaBuilder/RnaAccordion/RnaAccordion.tsx | 4 +- .../RnaBuilder/RnaEditor/RnaEditor.tsx | 10 ++-- .../RnaEditorExpanded.test.tsx | 11 +---- .../RnaEditorExpanded/RnaEditorExpanded.tsx | 4 +- .../RnaEditorExpanded.test.tsx.snap | 2 +- ...ts => useDisabledForSequenceMode.test.tsx} | 48 ++++++++++++------- .../hooks/useDisabledForSequenceMode.ts | 6 ++- .../src/hooks/stateHooks.ts | 6 +-- 20 files changed, 90 insertions(+), 124 deletions(-) rename packages/ketcher-macromolecules/src/components/monomerLibrary/monomerLibraryItem/hooks/{useDisabledForSequenceMode.test.ts => useDisabledForSequenceMode.test.tsx} (82%) diff --git a/packages/ketcher-core/src/application/editor/Editor.ts b/packages/ketcher-core/src/application/editor/Editor.ts index ea9a77dd5c..1bbab5e76b 100644 --- a/packages/ketcher-core/src/application/editor/Editor.ts +++ b/packages/ketcher-core/src/application/editor/Editor.ts @@ -339,12 +339,19 @@ export class CoreEditor { } public get isSequenceEditMode() { - return this.mode instanceof SequenceMode && this.mode.isEditMode; + return this?.mode instanceof SequenceMode && this?.mode.isEditMode; } public get isSequenceEditInRNABuilderMode() { return ( - this.mode instanceof SequenceMode && this.mode.isEditInRNABuilderMode + this?.mode instanceof SequenceMode && this?.mode.isEditInRNABuilderMode + ); + } + + public get isSequenceAnyEditMode() { + return ( + this?.mode instanceof SequenceMode && + (this?.mode.isEditMode || this?.mode.isEditInRNABuilderMode) ); } diff --git a/packages/ketcher-core/src/application/editor/modes/BaseMode.ts b/packages/ketcher-core/src/application/editor/modes/BaseMode.ts index f3ee085175..5313209475 100644 --- a/packages/ketcher-core/src/application/editor/modes/BaseMode.ts +++ b/packages/ketcher-core/src/application/editor/modes/BaseMode.ts @@ -141,8 +141,12 @@ export abstract class BaseMode { async onPaste(event: ClipboardEvent) { if (!this.checkIfTargetIsInput(event)) { if (isClipboardAPIAvailable()) { - if (this._pasteIsInProgress) return; + const isSequenceEditInRNABuilderMode = + CoreEditor.provideEditorInstance().isSequenceEditInRNABuilderMode; + + if (isSequenceEditInRNABuilderMode || this._pasteIsInProgress) return; this._pasteIsInProgress = true; + const clipboardData = await navigator.clipboard.read(); this.pasteFromClipboard(clipboardData).finally(() => { this._pasteIsInProgress = false; diff --git a/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts b/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts index 83e62202ea..b5472d94cc 100644 --- a/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts +++ b/packages/ketcher-core/src/application/editor/tools/SelectRectangle.ts @@ -137,14 +137,7 @@ class SelectRectangle implements BaseTool { } mousedown(event) { - const editor = CoreEditor.provideEditorInstance(); - - if ( - editor.mode instanceof SequenceMode && - (editor.mode.isEditMode || editor.mode.isEditInRNABuilderMode) - ) { - return; - } + if (CoreEditor.provideEditorInstance().isSequenceAnyEditMode) return; const renderer = event.target.__data__; this.mousePositionAfterMove = this.editor.lastCursorPositionOfCanvas; diff --git a/packages/ketcher-core/src/application/ketcher.ts b/packages/ketcher-core/src/application/ketcher.ts index f39f256135..c7740451c2 100644 --- a/packages/ketcher-core/src/application/ketcher.ts +++ b/packages/ketcher-core/src/application/ketcher.ts @@ -18,12 +18,7 @@ import { saveAs } from 'file-saver'; import { FormatterFactory, SupportedFormat } from './formatters'; import { GenerateImageOptions, StructService } from 'domain/services'; -import { - CoreEditor, - Editor, - defaultBondThickness, - SequenceMode, -} from './editor'; +import { CoreEditor, Editor, defaultBondThickness } from './editor'; import { Indigo } from 'application/indigo'; import { KetSerializer, MolfileFormat } from 'domain/serializers'; import { SGroup, Struct } from 'domain/entities'; @@ -351,11 +346,7 @@ export class Ketcher { } async setMolecule(structStr: string): Promise { - const editor = CoreEditor.provideEditorInstance(); - if ( - editor?.mode instanceof SequenceMode && - editor?.mode.isEditInRNABuilderMode - ) + if (CoreEditor.provideEditorInstance().isSequenceEditInRNABuilderMode) return; runAsyncAction(async () => { @@ -380,11 +371,7 @@ export class Ketcher { } async addFragment(structStr: string): Promise { - const editor = CoreEditor.provideEditorInstance(); - if ( - editor?.mode instanceof SequenceMode && - editor?.mode.isEditInRNABuilderMode - ) + if (CoreEditor.provideEditorInstance().isSequenceEditInRNABuilderMode) return; runAsyncAction(async () => { diff --git a/packages/ketcher-core/src/application/render/renderers/sequence/BaseSequenceItemRenderer.ts b/packages/ketcher-core/src/application/render/renderers/sequence/BaseSequenceItemRenderer.ts index fa0abb2129..963f2c902c 100644 --- a/packages/ketcher-core/src/application/render/renderers/sequence/BaseSequenceItemRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/sequence/BaseSequenceItemRenderer.ts @@ -4,7 +4,6 @@ import { SubChainNode } from 'domain/entities/monomer-chains/types'; import { BaseSequenceRenderer } from 'application/render/renderers/sequence/BaseSequenceRenderer'; import { BaseSubChain } from 'domain/entities/monomer-chains/BaseSubChain'; import { CoreEditor } from 'application/editor/internal'; -import { SequenceMode } from 'application/editor/modes'; import { EmptySequenceNode } from 'domain/entities/EmptySequenceNode'; import { editorEvents } from 'application/editor/editorEvents'; import assert from 'assert'; @@ -74,17 +73,11 @@ export abstract class BaseSequenceItemRenderer extends BaseSequenceRenderer { } protected get isSequenceEditModeTurnedOn() { - const editor = CoreEditor.provideEditorInstance(); - - return editor.mode instanceof SequenceMode && editor.mode.isEditMode; + return CoreEditor.provideEditorInstance().isSequenceEditMode; } protected get isSequenceEditInRnaBuilderModeTurnedOn() { - const editor = CoreEditor.provideEditorInstance(); - - return ( - editor.mode instanceof SequenceMode && editor.mode.isEditInRNABuilderMode - ); + return CoreEditor.provideEditorInstance().isSequenceEditInRNABuilderMode; } private appendRootElement() { diff --git a/packages/ketcher-core/src/application/render/renderers/sequence/SequenceRenderer.ts b/packages/ketcher-core/src/application/render/renderers/sequence/SequenceRenderer.ts index c138e601d0..7e012b8e1a 100644 --- a/packages/ketcher-core/src/application/render/renderers/sequence/SequenceRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/sequence/SequenceRenderer.ts @@ -25,7 +25,6 @@ import { Chain } from 'domain/entities/monomer-chains/Chain'; import { EmptySubChain } from 'domain/entities/monomer-chains/EmptySubChain'; import { SubChainNode } from 'domain/entities/monomer-chains/types'; import { CoreEditor } from 'application/editor/internal'; -import { SequenceMode } from 'application/editor/modes'; import { RestoreSequenceCaretPositionOperation } from 'application/editor/operations/modes'; import assert from 'assert'; import { BaseSubChain } from 'domain/entities/monomer-chains/BaseSubChain'; @@ -80,9 +79,7 @@ export class SequenceRenderer { let currentMonomerIndexInChain = 0; let currentMonomerIndexOverall = 0; - const editor = CoreEditor.provideEditorInstance(); - const isEditMode = - editor.mode instanceof SequenceMode && editor.mode.isEditMode; + const isEditMode = CoreEditor.provideEditorInstance().isSequenceEditMode; if (isEditMode) { chainsCollection.chains.forEach((chain) => { diff --git a/packages/ketcher-macromolecules/src/Editor.tsx b/packages/ketcher-macromolecules/src/Editor.tsx index ee87884959..0c43e89526 100644 --- a/packages/ketcher-macromolecules/src/Editor.tsx +++ b/packages/ketcher-macromolecules/src/Editor.tsx @@ -24,7 +24,6 @@ import { Nucleotide, Nucleoside, NodeSelection, - SequenceMode, } from 'ketcher-core'; import { store } from 'state'; import { @@ -367,7 +366,9 @@ function Editor({ theme, togglerComponent }: EditorProps) { - + { @@ -427,12 +428,8 @@ function MenuComponent() { if (name === 'clear') { dispatch(selectTool('select-rectangle')); editor.events.selectTool.dispatch('select-rectangle'); - if ( - editor.mode instanceof SequenceMode && - editor.mode.isEditInRNABuilderMode - ) { + if (isSequenceEditInRNABuilderMode) resetRnaBuilderAfterSequenceUpdate(dispatch, editor); - } } else { dispatch(selectTool(name)); } diff --git a/packages/ketcher-macromolecules/src/components/LayoutModeButton/LayoutModeButton.tsx b/packages/ketcher-macromolecules/src/components/LayoutModeButton/LayoutModeButton.tsx index c7204e1b84..295e3cf8f1 100644 --- a/packages/ketcher-macromolecules/src/components/LayoutModeButton/LayoutModeButton.tsx +++ b/packages/ketcher-macromolecules/src/components/LayoutModeButton/LayoutModeButton.tsx @@ -17,18 +17,14 @@ import { useEffect, useState } from 'react'; import { Menu } from 'components/menu'; import { MenuContext } from '../../contexts'; -import { - useAppSelector, - useLayoutMode, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppSelector, useLayoutMode } from 'hooks'; import { selectEditor } from 'state/common'; export const LayoutModeButton = () => { const [activeMode, setActiveMode] = useState('flex-layout-mode'); const editor = useAppSelector(selectEditor); const layoutMode = useLayoutMode(); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const menuContext = { isActive: (mode) => activeMode === mode, diff --git a/packages/ketcher-macromolecules/src/components/SequenceTypeButton/SequenceTypeDropdown.tsx b/packages/ketcher-macromolecules/src/components/SequenceTypeButton/SequenceTypeDropdown.tsx index 23c173a728..4449221328 100644 --- a/packages/ketcher-macromolecules/src/components/SequenceTypeButton/SequenceTypeDropdown.tsx +++ b/packages/ketcher-macromolecules/src/components/SequenceTypeButton/SequenceTypeDropdown.tsx @@ -15,11 +15,7 @@ ***************************************************************************/ import { useEffect, useState } from 'react'; -import { - useAppSelector, - useLayoutMode, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppSelector, useLayoutMode } from 'hooks'; import { selectEditor } from 'state/common'; import { SequenceType } from 'ketcher-core'; import { StyledDropdown } from 'components/modal/save/Save.styles'; @@ -43,7 +39,7 @@ export const SequenceTypeDropdown = () => { const [isSequenceMode, setIsSequenceMode] = useState(false); const editor = useAppSelector(selectEditor); const layoutMode = useLayoutMode(); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const isDisabled = isSequenceEditInRNABuilderMode; const dropdownOptions = [ diff --git a/packages/ketcher-macromolecules/src/components/contextMenu/RNAContextMenu.tsx b/packages/ketcher-macromolecules/src/components/contextMenu/RNAContextMenu.tsx index d970fad2ed..86bf996a30 100644 --- a/packages/ketcher-macromolecules/src/components/contextMenu/RNAContextMenu.tsx +++ b/packages/ketcher-macromolecules/src/components/contextMenu/RNAContextMenu.tsx @@ -1,10 +1,6 @@ import { Item, ItemParams, Separator } from 'react-contexify'; import { openModal } from 'state/modal'; -import { - useAppDispatch, - useAppSelector, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppDispatch, useAppSelector } from 'hooks'; import { ReactElement } from 'react'; import { CONTEXT_MENU_ID } from './types'; import { selectCurrentTabIndex, setSelectedTabIndex } from 'state/library'; @@ -12,6 +8,7 @@ import { selectActivePresetForContextMenu } from 'state/rna-builder'; import { StyledMenu } from './styles'; import { createPortal } from 'react-dom'; import { KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR } from 'ketcher-react'; +import { selectEditor } from 'state/common'; export const RNAContextMenu = () => { const RNA_TAB_INDEX = 2; @@ -20,7 +17,8 @@ export const RNAContextMenu = () => { selectActivePresetForContextMenu, ); const selectedTabIndex = useAppSelector(selectCurrentTabIndex); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const editor = useAppSelector(selectEditor); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const RNAMenus = [ { name: 'duplicateandedit', title: 'Duplicate and Edit...' }, { name: 'edit', title: 'Edit...', seperator: true }, diff --git a/packages/ketcher-macromolecules/src/components/contextMenu/SequenceItemContextMenu/SequenceItemContextMenu.tsx b/packages/ketcher-macromolecules/src/components/contextMenu/SequenceItemContextMenu/SequenceItemContextMenu.tsx index ff64c51b08..0a181f9fa5 100644 --- a/packages/ketcher-macromolecules/src/components/contextMenu/SequenceItemContextMenu/SequenceItemContextMenu.tsx +++ b/packages/ketcher-macromolecules/src/components/contextMenu/SequenceItemContextMenu/SequenceItemContextMenu.tsx @@ -4,11 +4,7 @@ import { CONTEXT_MENU_ID } from '../types'; import { StyledMenu } from '../styles'; import { createPortal } from 'react-dom'; import { KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR } from 'ketcher-react'; -import { - useAppDispatch, - useAppSelector, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppDispatch, useAppSelector } from 'hooks'; import { selectEditor } from 'state/common'; import { BaseSequenceItemRenderer, NodesSelection } from 'ketcher-core'; import { setSelectedTabIndex } from 'state/library'; @@ -34,7 +30,7 @@ export const SequenceItemContextMenu = ({ const editor = useAppSelector(selectEditor); const dispatch = useAppDispatch(); const menuProps = generateSequenceContextMenuProps(selections); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const menuItems = [ { diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/MonomerLibrary.tsx b/packages/ketcher-macromolecules/src/components/monomerLibrary/MonomerLibrary.tsx index 3949800d38..c20c98a0f7 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/MonomerLibrary.tsx +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/MonomerLibrary.tsx @@ -16,12 +16,7 @@ import React, { ChangeEvent, useRef } from 'react'; import { Tabs } from 'components/shared/Tabs'; import { tabsContent } from 'components/monomerLibrary/tabsContent'; -import { - useAppDispatch, - useAppSelector, - useLayoutMode, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppDispatch, useAppSelector, useLayoutMode } from 'hooks'; import { setSearchFilter } from 'state/library'; import { Icon } from 'ketcher-react'; import { IRnaPreset } from './RnaBuilder/types'; @@ -42,11 +37,15 @@ import { const COPY = '_Copy'; -const MonomerLibrary = React.memo(() => { +type MonomerLibraryProps = { + isSequenceEditInRNABuilderMode?: boolean; +}; + +const MonomerLibrary = React.memo((props: MonomerLibraryProps) => { const presetsRef = useRef([]); const dispatch = useAppDispatch(); const layoutMode = useLayoutMode(); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = props?.isSequenceEditInRNABuilderMode; const isSequenceMode = layoutMode === 'sequence-layout-mode'; const isDisabledTabs = isSequenceMode; const isDisabledTabsPanels = diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaAccordion/RnaAccordion.tsx b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaAccordion/RnaAccordion.tsx index 9746302ab5..46d5533411 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaAccordion/RnaAccordion.tsx +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaAccordion/RnaAccordion.tsx @@ -15,7 +15,7 @@ ***************************************************************************/ import { MonomerGroup } from 'components/monomerLibrary/monomerLibraryGroup'; -import { useAppSelector, useSequenceEditInRNABuilderMode } from 'hooks'; +import { useAppSelector } from 'hooks'; import { IconName } from 'ketcher-react'; import { useEffect, useState } from 'react'; import { @@ -79,7 +79,7 @@ export const RnaAccordion = ({ libraryName, duplicatePreset, editPreset }) => { const isActivePresetNewAndEmpty = useAppSelector( selectIsActivePresetNewAndEmpty, ); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const [expandedAccordion, setExpandedAccordion] = useState(activeRnaBuilderItem); diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditor.tsx b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditor.tsx index ab2f73f33c..797ed745d3 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditor.tsx +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditor.tsx @@ -23,11 +23,7 @@ import { RnaEditorContainer, StyledHeader, } from './styles'; -import { - useAppDispatch, - useAppSelector, - useSequenceEditInRNABuilderMode, -} from 'hooks'; +import { useAppDispatch, useAppSelector } from 'hooks'; import { createNewPreset, RnaBuilderPresetsItem, @@ -38,6 +34,7 @@ import { setIsEditMode, } from 'state/rna-builder'; import { scrollToElement } from 'helpers/dom'; +import { selectEditor } from 'state/common'; export const scrollToSelectedPreset = (presetName) => { scrollToElement(`[data-rna-preset-item-name="${presetName}"]`); @@ -50,7 +47,8 @@ export const scrollToSelectedMonomer = (monomerId) => { export const RnaEditor = ({ duplicatePreset }) => { const activePreset = useAppSelector(selectActivePreset); const isEditMode = useAppSelector(selectIsEditMode); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const editor = useAppSelector(selectEditor); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const activePresetFullName = selectPresetFullName(activePreset); const dispatch = useAppDispatch(); diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.test.tsx b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.test.tsx index 1de79f4bda..830b6a7b00 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.test.tsx +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.test.tsx @@ -2,15 +2,6 @@ import { Entities } from 'ketcher-core'; import { fireEvent, render, screen } from '@testing-library/react'; import { RnaEditorExpanded } from 'components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded'; import { EmptyFunction } from 'helpers'; -import { useSequenceEditInRNABuilderMode } from 'hooks'; - -jest.mock('../../../../../hooks/stateHooks', () => ({ - ...jest.requireActual('../../../../../hooks/stateHooks'), - useSequenceEditInRNABuilderMode: jest.fn(), -})); - -const mockUseSequenceEditInRNABuilderMode = - useSequenceEditInRNABuilderMode as jest.Mock; describe('Test Rna Editor Expanded component', () => { it('should render correctly in edit mode', async () => { @@ -42,11 +33,11 @@ describe('Test Rna Editor Expanded component', () => { }); it('should render correctly in edit mode with modification of sequence', async () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); render( withThemeAndStoreProvider( , { + editor: { editor: { isSequenceEditInRNABuilderMode: true } }, rnaBuilder: { activePreset: {}, sequenceSelectionName: '2 nucleotides', diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.tsx b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.tsx index 399ce4170e..20e6f23868 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.tsx +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/RnaEditorExpanded.tsx @@ -50,7 +50,7 @@ import { setSequenceSelectionName, selectIsActivePresetNewAndEmpty, } from 'state/rna-builder'; -import { useAppSelector, useSequenceEditInRNABuilderMode } from 'hooks'; +import { useAppSelector } from 'hooks'; import { scrollToSelectedMonomer, scrollToSelectedPreset, @@ -109,7 +109,7 @@ export const RnaEditorExpanded = ({ // For sequence edit in RNA Builder mode const sequenceSelection = useAppSelector(selectSequenceSelection); const sequenceSelectionName = useAppSelector(selectSequenceSelectionName); - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const [isSequenceSelectionUpdated, setIsSequenceSelectionUpdated] = useState(false); const [sequenceSelectionGroupNames, setSequenceSelectionGroupNames] = diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/__snapshots__/RnaEditorExpanded.test.tsx.snap b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/__snapshots__/RnaEditorExpanded.test.tsx.snap index 2079144e90..08ed800f56 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/__snapshots__/RnaEditorExpanded.test.tsx.snap +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/RnaBuilder/RnaEditor/RnaEditorExpanded/__snapshots__/RnaEditorExpanded.test.tsx.snap @@ -347,7 +347,7 @@ exports[`Test Rna Editor Expanded component should render correctly in edit mode exports[`Test Rna Editor Expanded component should render correctly in view mode 1`] = `
({ useSelector: jest.fn(), })); -jest.mock('../../../../hooks/stateHooks', () => ({ - ...jest.requireActual('../../../../hooks/stateHooks'), - useSequenceEditInRNABuilderMode: jest.fn(), +jest.mock('hooks', () => ({ + useAppSelector: jest.fn(), })); -const mockUseSequenceEditInRNABuilderMode = - useSequenceEditInRNABuilderMode as jest.Mock; - const mockUseSelector = useSelector as jest.Mock; +const mockUseAppSelector = useAppSelector as jest.Mock; const monomer: MonomerItemType = { label: 'for test', @@ -31,7 +28,9 @@ const monomer: MonomerItemType = { describe('useDisabledForSequenceMode hook', () => { it('should return false if isSequenceEditInRNABuilderMode is false', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(false); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: false, + }); const { result } = renderHook(() => useDisabledForSequenceMode(monomer, MonomerGroups.SUGARS), ); @@ -40,7 +39,9 @@ describe('useDisabledForSequenceMode hook', () => { describe('for Bases', () => { it('should return false if there is R1', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); monomer.props.MonomerCaps = { R1: 'H' }; const { result } = renderHook(() => useDisabledForSequenceMode(monomer, MonomerGroups.BASES), @@ -49,7 +50,9 @@ describe('useDisabledForSequenceMode hook', () => { }); it('should return true if there is no R1', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); monomer.props.MonomerCaps = {}; const { result } = renderHook(() => useDisabledForSequenceMode(monomer, MonomerGroups.BASES), @@ -60,7 +63,9 @@ describe('useDisabledForSequenceMode hook', () => { describe('for Phosphates', () => { it('should return false if there is R1 and R2', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); monomer.props.MonomerCaps = { R1: 'H', R2: 'H' }; const { result } = renderHook(() => useDisabledForSequenceMode(monomer, MonomerGroups.PHOSPHATES), @@ -69,8 +74,9 @@ describe('useDisabledForSequenceMode hook', () => { }); it('should return true if there is no R1 or R2', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); - + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); // Without R2 monomer.props.MonomerCaps = { R1: 'H' }; const { result: result1 } = renderHook(() => @@ -89,7 +95,9 @@ describe('useDisabledForSequenceMode hook', () => { describe('for Sugars', () => { it('should return false if there is R2 and R3 and isSequenceFirstsOnlyNucleoelementsSelected is true', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); mockUseSelector.mockImplementation(() => true); monomer.props.MonomerCaps = { R2: 'H', R3: 'H' }; const { result } = renderHook(() => @@ -99,7 +107,9 @@ describe('useDisabledForSequenceMode hook', () => { }); it('should return true if there is no R2 or R3 and isSequenceFirstsOnlyNucleoelementsSelected is true', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); mockUseSelector.mockImplementation(() => true); monomer.props.MonomerCaps = { R2: 'H' }; @@ -118,7 +128,9 @@ describe('useDisabledForSequenceMode hook', () => { }); it('should return false if there is R1, R2, R3 and isSequenceFirstsOnlyNucleoelementsSelected is false', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); mockUseSelector.mockImplementation(() => false); monomer.props.MonomerCaps = { R1: 'H', R2: 'H', R3: 'H' }; const { result } = renderHook(() => @@ -128,7 +140,9 @@ describe('useDisabledForSequenceMode hook', () => { }); it('should return true if there is no R1 or R2 or R3 and isSequenceFirstsOnlyNucleoelementsSelected is false', () => { - mockUseSequenceEditInRNABuilderMode.mockReturnValue(true); + mockUseAppSelector.mockReturnValue({ + isSequenceEditInRNABuilderMode: true, + }); mockUseSelector.mockImplementation(() => true); // Without R3 diff --git a/packages/ketcher-macromolecules/src/components/monomerLibrary/monomerLibraryItem/hooks/useDisabledForSequenceMode.ts b/packages/ketcher-macromolecules/src/components/monomerLibrary/monomerLibraryItem/hooks/useDisabledForSequenceMode.ts index 377b2cb7d7..3c72a25ebd 100644 --- a/packages/ketcher-macromolecules/src/components/monomerLibrary/monomerLibraryItem/hooks/useDisabledForSequenceMode.ts +++ b/packages/ketcher-macromolecules/src/components/monomerLibrary/monomerLibraryItem/hooks/useDisabledForSequenceMode.ts @@ -2,13 +2,15 @@ import { MonomerGroups, MonomerItemType } from 'ketcher-core'; import { useSelector } from 'react-redux'; import { useEffect, useState } from 'react'; import { selectIsSequenceFirstsOnlyNucleotidesSelected } from 'state/rna-builder'; -import { useSequenceEditInRNABuilderMode } from 'hooks'; +import { useAppSelector } from 'hooks'; +import { selectEditor } from 'state/common'; const useDisabledForSequenceMode = ( item: MonomerItemType, groupName?: MonomerGroups, ) => { - const isSequenceEditInRNABuilderMode = useSequenceEditInRNABuilderMode(); + const editor = useAppSelector(selectEditor); + const isSequenceEditInRNABuilderMode = editor?.isSequenceEditInRNABuilderMode; const isSequenceFirstsOnlyNucleoelementsSelected = useSelector( selectIsSequenceFirstsOnlyNucleotidesSelected, ); diff --git a/packages/ketcher-macromolecules/src/hooks/stateHooks.ts b/packages/ketcher-macromolecules/src/hooks/stateHooks.ts index 7a5750ae0f..8c1acb1df5 100644 --- a/packages/ketcher-macromolecules/src/hooks/stateHooks.ts +++ b/packages/ketcher-macromolecules/src/hooks/stateHooks.ts @@ -18,7 +18,7 @@ import { useCallback, useEffect, useState } from 'react'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import { AppDispatch, RootState } from 'state'; import { selectEditor } from 'state/common'; -import { LayoutMode, SequenceMode } from 'ketcher-core'; +import { LayoutMode } from 'ketcher-core'; export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector; @@ -46,10 +46,8 @@ export function useLayoutMode() { export function useSequenceEditInRNABuilderMode() { const editor = useAppSelector(selectEditor); - const isSequenceEditInRNABuilderModeInitial = - editor?.mode instanceof SequenceMode && editor?.mode.isEditInRNABuilderMode; const [isSequenceEditInRNABuilderMode, setIsSequenceEditInRNABuilderMode] = - useState(isSequenceEditInRNABuilderModeInitial); + useState(editor?.isSequenceEditInRNABuilderMode); const onSequenceEditInRNABuilderModeChange = (value: boolean) => { setIsSequenceEditInRNABuilderMode(value);