diff --git a/package.json b/package.json index 1ac66a8ed..1e11f161d 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "dependencies": { "@tinymce/tinymce-react": "^3.13.0", + "tinymce": "^5.10.2", "babel-polyfill": "6.26.0", "react-responsive": "8.2.0", "react-transition-group": "4.4.2" diff --git a/src/editors/EditorPage.jsx b/src/editors/EditorPage.jsx index 055a5bec2..64c15bb5e 100644 --- a/src/editors/EditorPage.jsx +++ b/src/editors/EditorPage.jsx @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { ModalDialog } from '@edx/paragon'; import { FormattedMessage } from '@edx/frontend-platform/i18n'; import TextEditor from './TextEditor/TextEditor'; import VideoEditor from './VideoEditor/VideoEditor'; @@ -41,20 +40,17 @@ export default function EditorPage({ blockId={blockId} studioEndpointUrl={studioEndpointUrl} > - {}} - hasCloseButton={false} - variant="dark" - > -
+
+
{selectEditor(blockType)}
- +
); } diff --git a/src/editors/TextEditor/ImageUpload/Wizard/ImageUploadModal.jsx b/src/editors/TextEditor/ImageUpload/Wizard/ImageUploadModal.jsx new file mode 100644 index 000000000..00cb118d5 --- /dev/null +++ b/src/editors/TextEditor/ImageUpload/Wizard/ImageUploadModal.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { ModalDialog, ActionRow, Button } from '@edx/paragon'; + +const ImageUploadModal = ({ isOpen, close }) => ( + + + + Im a dialog box + + + +

+ Im baby palo santo ugh celiac fashion axe. + La croix lo-fi venmo whatever. + Beard man braid migas single-origin coffee forage ramps. + Tumeric messenger bag bicycle rights wayfarers, try-hard cronut blue bottle health goth. + Sriracha tumblr cardigan, cloud bread succulents tumeric copper mug marfa semiotics woke next + level organic roof party +1 try-hard. +

+
+ + + + Cancel + + + + +
+); + +ImageUploadModal.propTypes = { + isOpen: PropTypes.bool, + close: PropTypes.func, +}; +ImageUploadModal.defaultProps = { + isOpen: false, + close: () => {}, +}; +export default ImageUploadModal; diff --git a/src/editors/TextEditor/TextEditor.jsx b/src/editors/TextEditor/TextEditor.jsx index 7efb84ddf..45bfb4f4c 100644 --- a/src/editors/TextEditor/TextEditor.jsx +++ b/src/editors/TextEditor/TextEditor.jsx @@ -1,17 +1,36 @@ import React, { useContext } from 'react'; -import { Spinner, Toast } from '@edx/paragon'; import { Editor } from '@tinymce/tinymce-react'; import { FormattedMessage } from '@edx/frontend-platform/i18n'; +import { + useToggle, Spinner, Toast, +} from '@edx/paragon'; import EditorPageContext from '../EditorPageContext'; import { ActionStates } from '../data/constants'; +import ImageUploadModal from './ImageUpload/Wizard/ImageUploadModal'; + +import 'tinymce'; +import 'tinymce/themes/silver'; +import 'tinymce/skins/ui/oxide/skin.css'; +import 'tinymce/icons/default'; +import 'tinymce/plugins/link'; +import 'tinymce/plugins/table'; +import 'tinymce/plugins/codesample'; +import 'tinymce/plugins/emoticons'; +import 'tinymce/plugins/emoticons/js/emojis'; +import 'tinymce/plugins/charmap'; +import 'tinymce/plugins/code'; +import 'tinymce/plugins/autoresize'; const TextEditor = () => { const { blockValue, blockError, blockLoading, editorRef, } = useContext(EditorPageContext); + const [isImageUploadModalOpen, openUploadModal, closeUploadModal] = useToggle(false); + return (
+ {}}> { ) : ( { editorRef.current = editor; }} + onInit={(evt, editor) => { + editorRef.current = editor; + }} initialValue={blockValue ? blockValue.data.data : ''} init={{ - height: '100%', + setup: (editor) => { + editor.ui.registry.addButton('imageuploadbutton', { + icon: 'image', + onAction: () => openUploadModal(), + }); + }, + plugins: 'link codesample emoticons table charmap code autoresize', menubar: false, - plugins: [ - 'advlist autolink lists link image charmap print preview anchor', - 'searchreplace visual blocks code fullscreen', - 'insertdatetime media table paste code help wordcount', - 'autoresize', - ], toolbar: 'undo redo | formatselect | ' + 'bold italic backcolor | alignleft aligncenter ' - + 'alignright alignjustify | bullist numlist outdent indent | ' - + 'removeformat | help', + + 'alignright alignjustify | bullist numlist outdent indent |' + + 'imageuploadbutton | link | emoticons | table | codesample | charmap |' + + 'removeformat | hr |code', + height: '100%', content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', - max_height: 900, - min_height: 700, + min_height: 1000, branding: false, }} /> diff --git a/src/setupTest.js b/src/setupTest.js index de956a28f..9984d6e31 100644 --- a/src/setupTest.js +++ b/src/setupTest.js @@ -6,6 +6,22 @@ import 'babel-polyfill'; Enzyme.configure({ adapter: new Adapter() }); +/* need to mock window for tinymce on import, as it is JSDOM incompatible */ + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); + // These configuration values are usually set in webpack's EnvironmentPlugin however // Jest does not use webpack so we need to set these so for testing process.env.ACCESS_TOKEN_COOKIE_NAME = 'edx-jwt-cookie-header-payload';