From 80f378d5e654305ba58654fd91fd46dd82fa6131 Mon Sep 17 00:00:00 2001 From: ElenaOdnoshivkina <89905163+ElenaOdnoshivkina@users.noreply.github.com> Date: Mon, 14 Feb 2022 19:10:18 +0300 Subject: [PATCH 1/7] #1235 use iframe embed standalone version ketcher init error (#1250) * add post message event after ketcher init * fix comments --- example/src/App.tsx | 6 ++++++ example/src/typing.d.ts | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 example/src/typing.d.ts diff --git a/example/src/App.tsx b/example/src/App.tsx index 1ea12eb026..34edde9461 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -57,6 +57,12 @@ const App = () => { structServiceProvider={structServiceProvider} onInit={(ketcher: Ketcher) => { ;(global as any).ketcher = ketcher + window.parent.postMessage( + { + eventType: 'init' + }, + '*' + ) }} /> {polymerEditor && } diff --git a/example/src/typing.d.ts b/example/src/typing.d.ts new file mode 100644 index 0000000000..58e94b2555 --- /dev/null +++ b/example/src/typing.d.ts @@ -0,0 +1,13 @@ +declare global { + export interface IMessage { + eventType: string + data?: any + } + export interface Window { + postMessage( + message: IMessage, + targetOrigin: string, + transfer?: Transferable[] | undefined + ): void + } +} From 81423737c9f6794ff46f307d254c44d621200604 Mon Sep 17 00:00:00 2001 From: Viktoriia Fedotkina <94109373+ViktoriiaFedotkina@users.noreply.github.com> Date: Tue, 15 Feb 2022 14:29:13 +0300 Subject: [PATCH 2/7] #1239 create save file modal window (#1246) * add modal slice * Create Save modal * Refactor Save modal * Add input component, saveButton component * Refactor save component, add errors button * refactor buttons * Add tests * Refactor tests * change inputField name * change names in theme Co-authored-by: ElenaOdnoshivkina <89905163+ElenaOdnoshivkina@users.noreply.github.com> --- .../jest.config.js | 3 +- .../ketcher-polymer-editor-react/package.json | 7 +- .../src/Editor.tsx | 36 +-- .../src/__snapshots__/Editor.test.tsx.snap | 136 ++++----- .../src/assets/icons/files/error.svg | 4 + .../src/assets/icons/files/save.svg | 4 + .../components/dummyDialog/DummyDialog.tsx | 60 ---- .../modal/modalContainer/ModalContainer.tsx | 37 +++ .../components/modal/modalContainer/index.ts | 17 ++ .../modalContainer/modalComponentList.ts | 21 ++ .../src/components/modal/save/Save.test.tsx | 72 +++++ .../src/components/modal/save/Save.tsx | 212 ++++++++++++++ .../save/__snapshots__/Save.test.tsx.snap | 276 ++++++++++++++++++ .../src/components/modal/save/index.ts | 17 ++ .../modal/save/saveButton/SaveButton.test.tsx | 43 +++ .../modal/save/saveButton/SaveButton.tsx | 54 ++++ .../components/modal/save/saveButton/index.ts | 17 ++ .../notationInput/notationContainer.tsx | 8 +- .../notationInput/notationInput.tsx | 6 +- .../shared/actionButton/ActionButton.tsx | 3 +- .../dropDown/__tests__/dropDown.test.tsx | 6 +- .../components/shared/dropDown/dropDown.tsx | 17 +- .../src/components/shared/icon/icon.tsx | 6 +- .../components/shared/modal/Modal.test.tsx | 7 +- .../src/components/shared/modal/Modal.tsx | 7 +- .../modal/__snapshots__/Modal.test.tsx.snap | 2 +- .../shared/textEditor/TextField.tsx | 70 +++++ .../src/components/shared/textEditor/index.ts | 17 ++ .../shared/textInputField/TextInputField.tsx | 74 +++++ .../components/shared/textInputField/index.ts | 17 ++ .../src/helpers/formats/formatProperties.ts | 41 +++ .../src/helpers/formats/index.ts | 18 ++ .../formats/supportedFormatProperties.ts | 42 +++ .../src/helpers/index.ts | 17 ++ .../src/state/modal/index.ts | 16 + .../src/state/modal/modalSlice.ts | 51 ++++ .../src/state/store.ts | 4 +- .../src/theming/defaultTheme/defaultTheme.ts | 21 +- .../src/theming/defaultTheme/theme.types.ts | 13 + .../theming/globalStyles/getGlobalStyles.ts | 9 + .../tsconfig.json | 4 +- yarn.lock | 130 ++++++++- 42 files changed, 1438 insertions(+), 184 deletions(-) create mode 100644 packages/ketcher-polymer-editor-react/src/assets/icons/files/error.svg create mode 100644 packages/ketcher-polymer-editor-react/src/assets/icons/files/save.svg delete mode 100644 packages/ketcher-polymer-editor-react/src/components/dummyDialog/DummyDialog.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/ModalContainer.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/modalComponentList.ts create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/Save.test.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/Save.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/__snapshots__/Save.test.tsx.snap create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/saveButton/SaveButton.test.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/saveButton/SaveButton.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/modal/save/saveButton/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/components/shared/textEditor/TextField.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/shared/textEditor/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/components/shared/textInputField/TextInputField.tsx create mode 100644 packages/ketcher-polymer-editor-react/src/components/shared/textInputField/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/helpers/formats/formatProperties.ts create mode 100644 packages/ketcher-polymer-editor-react/src/helpers/formats/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/helpers/formats/supportedFormatProperties.ts create mode 100644 packages/ketcher-polymer-editor-react/src/helpers/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/state/modal/index.ts create mode 100644 packages/ketcher-polymer-editor-react/src/state/modal/modalSlice.ts diff --git a/packages/ketcher-polymer-editor-react/jest.config.js b/packages/ketcher-polymer-editor-react/jest.config.js index 508f20acec..775a5324c7 100644 --- a/packages/ketcher-polymer-editor-react/jest.config.js +++ b/packages/ketcher-polymer-editor-react/jest.config.js @@ -14,7 +14,8 @@ module.exports = { '^theming(.*)$': '/src/theming/$1', '^hooks(.*)$': '/src/hooks/$1', '^assets(.*)$': '/src/assets/$1', - '^test-utils(.*)$': '/src/test-utils/$1' + '^test-utils(.*)$': '/src/test-utils/$1', + '^helpers(.*)$': '/src/helpers/$1' }, setupFilesAfterEnv: ['/src/testsSetup.ts'] } diff --git a/packages/ketcher-polymer-editor-react/package.json b/packages/ketcher-polymer-editor-react/package.json index d223fb7a4e..4ef6e71595 100644 --- a/packages/ketcher-polymer-editor-react/package.json +++ b/packages/ketcher-polymer-editor-react/package.json @@ -51,6 +51,7 @@ "@mui/material": "^5.2.4", "@reduxjs/toolkit": "^1.7.1", "clsx": "^1.1.1", + "file-saver": "^2.0.5", "lodash": "^4.17.21", "react-redux": "^7.2.1", "redux": "^4.0.5", @@ -70,9 +71,9 @@ "@rollup/plugin-replace": "^2.3.4", "@rollup/plugin-strip": "^2.0.0", "@svgr/rollup": "^5.4.0", - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.5.0", - "@testing-library/user-event": "^7.2.1", + "@testing-library/jest-dom": "^5.16.2", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.0.3", "@types/lodash": "^4.14.178", "@types/node": "^16.11.12", diff --git a/packages/ketcher-polymer-editor-react/src/Editor.tsx b/packages/ketcher-polymer-editor-react/src/Editor.tsx index 65682d5e60..a22ab69bec 100644 --- a/packages/ketcher-polymer-editor-react/src/Editor.tsx +++ b/packages/ketcher-polymer-editor-react/src/Editor.tsx @@ -15,7 +15,7 @@ ***************************************************************************/ import { Provider } from 'react-redux' -import { useEffect, useRef, useState } from 'react' +import { useEffect, useRef } from 'react' import { Global, ThemeProvider } from '@emotion/react' import { createTheme } from '@mui/material/styles' import { merge } from 'lodash' @@ -35,8 +35,11 @@ import { Menu } from 'components/menu' import { selectTool } from 'state/common' import { useAppDispatch } from 'hooks' import { Logo } from 'components/Logo' -import { ActionButton } from 'components/shared/actionButton' -import { DummyDialog } from 'components/dummyDialog/DummyDialog' +import { openModal } from 'state/modal' +import { + modalComponentList, + ModalContainer +} from 'components/modal/modalContainer' const muiTheme = createTheme(muiOverrides) @@ -58,8 +61,6 @@ function Editor({ onInit, theme }: EditorProps) { const mergedTheme: MergedThemeType = merge(muiTheme, { ketcher: editorTheme }) - const [isModalOpen, setIsModalOpen] = useState(false) - useEffect(() => { onInit?.() }, [onInit]) @@ -67,9 +68,9 @@ function Editor({ onInit, theme }: EditorProps) { return ( -
- + +
@@ -88,18 +89,7 @@ function Editor({ onInit, theme }: EditorProps) { -
- { - setIsModalOpen(true) - }} - /> - -
+
@@ -111,12 +101,18 @@ function MenuComponent() { const menuItemChanged = (name) => { dispatch(selectTool(name)) + if (modalComponentList[name]) { + dispatch(openModal(name)) + } } return ( - + + + + diff --git a/packages/ketcher-polymer-editor-react/src/__snapshots__/Editor.test.tsx.snap b/packages/ketcher-polymer-editor-react/src/__snapshots__/Editor.test.tsx.snap index fa3fd9de60..5a0baec8c3 100644 --- a/packages/ketcher-polymer-editor-react/src/__snapshots__/Editor.test.tsx.snap +++ b/packages/ketcher-polymer-editor-react/src/__snapshots__/Editor.test.tsx.snap @@ -20,19 +20,35 @@ Object {
- +
+ +
+ +
+
+
Polymer Editor @@ -445,22 +461,6 @@ Object { EPAM
-
- -
, @@ -480,19 +480,35 @@ Object {
- +
+ +
+ +
+
+
Polymer Editor @@ -905,22 +921,6 @@ Object { EPAM
-
- -
, "debug": [Function], diff --git a/packages/ketcher-polymer-editor-react/src/assets/icons/files/error.svg b/packages/ketcher-polymer-editor-react/src/assets/icons/files/error.svg new file mode 100644 index 0000000000..058c9bbe5a --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/assets/icons/files/error.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ketcher-polymer-editor-react/src/assets/icons/files/save.svg b/packages/ketcher-polymer-editor-react/src/assets/icons/files/save.svg new file mode 100644 index 0000000000..7b9c8c8dcd --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/assets/icons/files/save.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ketcher-polymer-editor-react/src/components/dummyDialog/DummyDialog.tsx b/packages/ketcher-polymer-editor-react/src/components/dummyDialog/DummyDialog.tsx deleted file mode 100644 index 6af699301f..0000000000 --- a/packages/ketcher-polymer-editor-react/src/components/dummyDialog/DummyDialog.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { useCallback } from 'react' -import { Modal } from 'components/shared/modal' -import { ActionButton } from 'components/shared/actionButton' - -export const DummyDialog = ({ isModalOpen, setIsModalOpen }) => { - const onCloseCallback = useCallback(() => { - setIsModalOpen(false) - }, [setIsModalOpen]) - - const onOkCallback = useCallback(() => { - setIsModalOpen(false) - }, [setIsModalOpen]) - - return ( - - -
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin at - lacinia ligula. Suspendisse at purus ullamcorper, convallis urna et, - pulvinar neque. Nunc nisl felis, congue quis arcu pretium, interdum - sagittis nibh. Fusce tristique urna tortor, vitae elementum urna - viverra et. Vestibulum at arcu ex. Pellentesque eros felis, dignissim - eu nulla a, laoreet mattis erat. Fusce et lectus scelerisque, - condimentum leo ut, semper felis. In non fringilla lorem, vel aliquet - arcu. Morbi tempor mi mi, et ultrices nisi ornare ac. Integer sodales - ullamcorper dignissim. Praesent blandit vehicula nisi. Donec tristique - iaculis mattis. Nunc ligula neque, scelerisque nec magna et, tincidunt - dignissim risus. Fusce ex mi, elementum id rhoncus ac, iaculis non - nibh. Duis iaculis turpis leo. Suspendisse ac nulla non nunc commodo - volutpat. Nunc nec laoreet mi, a mollis orci. Pellentesque vestibulum - mollis ligula ut semper. Class aptent taciti sociosqu ad litora - torquent per conubia nostra, per inceptos himenaeos. Etiam sapien leo, - aliquam vel hendrerit et, tristique ut massa. Donec et arcu nec risus - mollis auctor. Vestibulum efficitur sem non enim eleifend ullamcorper. - Duis quis tincidunt neque. Nulla at libero erat. Nam varius arcu in - ligula feugiat, vitae vulputate tortor vehicula. Aenean quis ornare - neque, vel fermentum nulla. Sed efficitur in dolor in porta. Sed - pulvinar lacus id risus commodo, quis suscipit nisl condimentum. Ut - sed volutpat dui. Quisque mattis magna non lorem tincidunt interdum. - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec commodo - maximus justo, sed lobortis leo pretium nec. Nullam ac justo eleifend, - interdum velit a, congue metus. Proin in sagittis mi. Class aptent - taciti sociosqu ad litora torquent per conubia nostra, per inceptos - himenaeos. Class aptent taciti sociosqu ad litora torquent per conubia - nostra, per inceptos himenaeos. Nam pellentesque urna nec cursus - fringilla. Morbi quis congue mauris, sit amet tempor sem. Nam felis - risus, ullamcorper vitae nibh non, vehicula porttitor velit. In purus - sapien, convallis id eleifend eleifend, imperdiet vitae nisi. Vivamus - semper, tortor et vestibulum aliquet, neque lacus vulputate turpis, - vel iaculis orci diam eu ex. In felis elit, volutpat in pulvinar in, - consectetur tempor ipsum. -
-
- - - - -
- ) -} diff --git a/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/ModalContainer.tsx b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/ModalContainer.tsx new file mode 100644 index 0000000000..956e343500 --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/ModalContainer.tsx @@ -0,0 +1,37 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +import { closeModal, selectModalIsOpen, selectModalName } from 'state/modal' +import { useAppDispatch, useAppSelector } from 'hooks' +import { useCallback } from 'react' +import { modalComponentList } from 'components/modal/modalContainer/modalComponentList' + +export const ModalContainer = () => { + const isOpen = useAppSelector(selectModalIsOpen) + const modalName = useAppSelector(selectModalName) + const dispatch = useAppDispatch() + + const handleClose = useCallback(() => { + dispatch(closeModal()) + }, [dispatch]) + + if (!modalName) return null + + const Component = modalComponentList[modalName] + + if (!Component) throw new Error(`There is no modal window named ${modalName}`) + + return +} diff --git a/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/index.ts b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/index.ts new file mode 100644 index 0000000000..d9880b296f --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/index.ts @@ -0,0 +1,17 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +export * from './ModalContainer' +export * from './modalComponentList' diff --git a/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/modalComponentList.ts b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/modalComponentList.ts new file mode 100644 index 0000000000..e63aa4caca --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/components/modal/modalContainer/modalComponentList.ts @@ -0,0 +1,21 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +import { Save } from 'components/modal/save' + +export const modalComponentList: Record = { + save: Save +} diff --git a/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.test.tsx b/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.test.tsx new file mode 100644 index 0000000000..1a79b97819 --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.test.tsx @@ -0,0 +1,72 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +import { render, screen } from 'test-utils' +import { Save } from 'components/modal/save' +import userEvent from '@testing-library/user-event' + +const mockOnClose = jest.fn() + +const mockProps = { + onClose: mockOnClose, + isModalOpen: true +} + +describe('Save modal', () => { + it('renders correctly', () => { + const view = render() + + const filenameInput = screen.getByRole('textbox', { + name: 'File name:' + }) + const fileFormatInput = screen.getByRole('button', { + name: 'MDL Molfile V3000' + }) + + expect(view).toMatchSnapshot() + expect(filenameInput).toBeVisible() + expect(filenameInput).toHaveValue('ketcher') + expect(fileFormatInput).toBeVisible() + }) + + it('renders dropdown options correctly', () => { + render() + + const fileFormat = screen.getByRole('button', { name: 'MDL Molfile V3000' }) + + userEvent.click(fileFormat) + const fileFormatDropdown = screen.getByRole('listbox') + const option1 = screen.getByRole('option', { name: 'MDL Molfile V3000' }) + const option2 = screen.getByRole('option', { name: 'HELM' }) + + expect(fileFormatDropdown).toBeVisible() + expect(option1).toBeVisible() + expect(option2).toBeVisible() + }) + + it('renders buttons correctly', () => { + render() + + const saveButton = screen.getByRole('button', { name: 'Save as file' }) + const filenameInput = screen.getByRole('textbox', { + name: 'File name:' + }) + + userEvent.clear(filenameInput) + + expect(saveButton).toBeDisabled() + }) +}) diff --git a/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.tsx b/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.tsx new file mode 100644 index 0000000000..41fdaed550 --- /dev/null +++ b/packages/ketcher-polymer-editor-react/src/components/modal/save/Save.tsx @@ -0,0 +1,212 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +import { useEffect, useState } from 'react' +import styled from '@emotion/styled' + +import { Modal } from 'components/shared/modal' +import { DropDown } from 'components/shared/dropDown' +import { Option } from 'components/shared/dropDown/dropDown' +import { TextField } from 'components/shared/textEditor' +import { TextInputField } from 'components/shared/textInputField' +import { SaveButton } from 'components/modal/save/saveButton' +import { getPropertiesByFormat, SupportedFormats } from 'helpers/formats' +import { ActionButton } from 'components/shared/actionButton' +import { Icon } from 'components/shared/icon' + +interface Props { + onClose: () => void + isModalOpen: boolean +} + +const options: Array