diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js index 6a259507f8051b8849fe824393f16d1c9951323a..54cc4a9cdf4f604028a8ac8c553b03b46a8c706c 100644 --- a/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js @@ -2,14 +2,11 @@ import { Service } from 'wax-prosemirror-services'; // import { MultipleChoicePlugin } from 'wax-prosemirror-plugins'; import MultipleChoiceQuestion from './MultipleChoiceQuestion'; import multipleChoiceNode from './schema/multipleChoiceNode'; -import TestComponentPortal from './components/TestComponentPortal'; +import TestComponent from './components/TestComponent'; class MultipleChoiceQuestionService extends Service { boot() { - // this.app.PmPlugins.add( - // 'multipleChoicePlugin', - // MultipleChoicePlugin('multipleChoicePlugin'), - // ); + } register() { @@ -18,7 +15,9 @@ class MultipleChoiceQuestionService extends Service { createNode({ multiple_choice: multipleChoiceNode, }); - // console.log(this.schema); + const addPortal = this.container.get('AddPortal'); + + addPortal({name: 'multiple_choice', component: TestComponent}) } } diff --git a/wax-prosemirror-core/src/Application.js b/wax-prosemirror-core/src/Application.js index 02ed531933a540ee7eeb96303333ee92a08797a1..63b621a865b604a833a1f1011274ef7362b4e7ce 100644 --- a/wax-prosemirror-core/src/Application.js +++ b/wax-prosemirror-core/src/Application.js @@ -39,6 +39,10 @@ export default class Application { this.config = this.container.get('Config'); } + setContext(context) { + this.context = context; + } + bootServices() { const services = this.config.get('config.services'); services.forEach(plugin => { diff --git a/wax-prosemirror-core/src/PortalContext.js b/wax-prosemirror-core/src/PortalContext.js index 0de864cce333ca6ff98e9e95e73b0bef4a585524..23e5ca9a1604145c37f03edbf82f8640f620c084 100644 --- a/wax-prosemirror-core/src/PortalContext.js +++ b/wax-prosemirror-core/src/PortalContext.js @@ -9,13 +9,14 @@ export const PortalContext = React.createContext({ export default props => { const [portal, setPortal] = useState({ - portals: [], - createPortal: (element, Component) => { - portal.portals.push({ + element: {}, + component: {}, + createPortal: (element, component) => { + setPortal({ + ...portal, element, - component: Component, + component, }); - setPortal({ ...portal, portals: [...portal.portals] }); }, }); diff --git a/wax-prosemirror-core/src/Wax.js b/wax-prosemirror-core/src/Wax.js index d54aa7fd118f6ed62eadd46fe659a7c2ab0c5ccc..222961eb8475fbc2c1528d4bf718c3b8dd8bb7f8 100644 --- a/wax-prosemirror-core/src/Wax.js +++ b/wax-prosemirror-core/src/Wax.js @@ -5,7 +5,7 @@ import debounce from 'lodash/debounce'; import { DOMSerializer } from 'prosemirror-model'; import WaxProvider from './WaxContext'; -import { PortalContext } from './PortalContext'; +import PortalProvider from './PortalContext'; import Application from './Application'; import WaxView from './WaxView'; @@ -23,7 +23,7 @@ let schema; const createApplication = props => { const application = Application.create(props); schema = application.getSchema(); - application.bootServices(); + // application.bootServices(); return application; }; @@ -94,7 +94,7 @@ const Wax = props => { const WaxRender = Layout.layoutComponent; return ( <WaxProvider app={application}> - <PortalContext> + <PortalProvider> <WaxView autoFocus={autoFocus} debug={debug} @@ -110,7 +110,7 @@ const Wax = props => { > {({ editor }) => <WaxRender className={className} editor={editor} />} </WaxView> - </PortalContext> + </PortalProvider> </WaxProvider> ); }; diff --git a/wax-prosemirror-core/src/WaxView.js b/wax-prosemirror-core/src/WaxView.js index 1a3fbdb32c79c5a4464b5c137dc6353bb3793a4c..3094211059b022d9d2a6c1c847e40fc43842b2ba 100644 --- a/wax-prosemirror-core/src/WaxView.js +++ b/wax-prosemirror-core/src/WaxView.js @@ -8,6 +8,7 @@ import { trackedTransaction } from 'wax-prosemirror-services'; import ComponentPlugin from './ComponentPlugin'; import { WaxContext } from './WaxContext'; +import { PortalContext } from './PortalContext'; import transformPasted from './helpers/TransformPasted'; import useWaxOptions from './useWaxOptions'; @@ -30,6 +31,11 @@ export default props => { const editorRef = useRef(); let view; const context = useContext(WaxContext); + const { createPortal } = useContext(PortalContext); + + context.app.setContext({ ...context, createPortal }); + + context.app.bootServices(); const options = useWaxOptions(props); const setEditorRef = useCallback( diff --git a/wax-prosemirror-core/src/useWaxOptions.js b/wax-prosemirror-core/src/useWaxOptions.js index 4f41a14cd6f63323c0a5bad0907e4f316d907cb5..41d0fbb69a8e80b5fc36394ee7e73d2e738ea69c 100644 --- a/wax-prosemirror-core/src/useWaxOptions.js +++ b/wax-prosemirror-core/src/useWaxOptions.js @@ -1,9 +1,7 @@ import { useContext } from 'react'; import { DOMParser } from 'prosemirror-model'; import { WaxContext } from './WaxContext'; -import { PortalContext } from './PortalContext'; import Placeholder from './plugins/placeholder'; -import PortalPlugin from './plugins/portalPlugin'; import defaultPlugins from './plugins/defaultPlugins'; const parser = schema => { @@ -19,7 +17,6 @@ const parser = schema => { export default ({ placeholder, targetFormat, value }) => { const context = useContext(WaxContext); - const { createPortal } = useContext(PortalContext); let finalPlugins = []; @@ -28,8 +25,6 @@ export default ({ placeholder, targetFormat, value }) => { return Placeholder({ content: placeholder }); }; - context.app.PmPlugins.add('portalPlugin', PortalPlugin({ createPortal })); - finalPlugins = defaultPlugins.concat([ createPlaceholder(placeholder), ...context.app.getPlugins(), diff --git a/wax-prosemirror-services/src/PortalService/PortalService.js b/wax-prosemirror-services/src/PortalService/PortalService.js index 5dc67774430acbb7a9794d57ee265c6b2511c582..a8d3c629d812f2fdc226243fc764b9ce254c1fb5 100644 --- a/wax-prosemirror-services/src/PortalService/PortalService.js +++ b/wax-prosemirror-services/src/PortalService/PortalService.js @@ -1,18 +1,33 @@ import Service from '../Service'; import PortalComponent from './components/PortalComponent'; +import PortalPlugin from './portalPlugin'; +import Portals from './Portals'; class PortalService extends Service { - boot() {} + boot() { + const portals = this.container.get('Portals'); + this.app.PmPlugins.add( + 'portalPlugin', + PortalPlugin({ + createPortal: this.app.context.createPortal, + portals: portals.getPortals(), + }), + ); + } register() { const layout = this.container.get('Layout'); layout.addComponent('waxPortals', PortalComponent); - // this.container.bind('MultipleChoiceQuestion').to(MultipleChoiceQuestion); - // const createNode = this.container.get('CreateNode'); - // createNode({ - // multiple_choice: multipleChoiceNode, - // }); - // console.log(this.schema); + + this.container.bind('Portals').to(Portals).inSingletonScope(); + + this.container.bind('AddPortal').toFactory(context => { + return portal => { + const schemaInstance = context.container.get('Portals'); + + schemaInstance.addPortal(portal); + }; + }); } } diff --git a/wax-prosemirror-services/src/PortalService/Portals.js b/wax-prosemirror-services/src/PortalService/Portals.js new file mode 100644 index 0000000000000000000000000000000000000000..133672fd245c7d8e3183d49907d5f3801f083c97 --- /dev/null +++ b/wax-prosemirror-services/src/PortalService/Portals.js @@ -0,0 +1,14 @@ +import { injectable } from 'inversify'; + +export default +@injectable() +class Portals { + portals = []; + addPortal(portal) { + this.portals.push(portal); + } + + getPortals() { + return this.portals; + } +} diff --git a/wax-prosemirror-services/src/PortalService/components/PortalComponent.js b/wax-prosemirror-services/src/PortalService/components/PortalComponent.js index 3bb081801701828189fdeb26699fa6ad6b7d80de..7ea44cdd72e330f6ae0be5298e085d13332ee8a4 100644 --- a/wax-prosemirror-services/src/PortalService/components/PortalComponent.js +++ b/wax-prosemirror-services/src/PortalService/components/PortalComponent.js @@ -1,22 +1,28 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { PortalContext } from 'wax-prosemirror-core'; import ReactDOM from 'react-dom'; import { v4 as uuidv4 } from 'uuid'; +import { isEmpty } from 'lodash'; import TestComponent from './TestComponent'; export default () => { - const { portals } = useContext(PortalContext); + const { element, component } = useContext(PortalContext); + + const [portals, setPortals] = useState([]); + + useEffect(() => { + if (!isEmpty(element)) { + portals.push({ dom: element, component, active: true }); + setPortals([...portals]); + } + }, [element]); - console.log(portals); return ( <> - {portals.length > 0 - ? ReactDOM.createPortal( - <TestComponent />, - document.getElementById('portalId'), - uuidv4(), - ) - : null} + {portals.length > 0 && + portals.map(({ dom, component: Component }) => { + return ReactDOM.createPortal(<Component />, dom, uuidv4()); + })} </> ); }; diff --git a/wax-prosemirror-core/src/plugins/portalPlugin.js b/wax-prosemirror-services/src/PortalService/portalPlugin.js similarity index 54% rename from wax-prosemirror-core/src/plugins/portalPlugin.js rename to wax-prosemirror-services/src/PortalService/portalPlugin.js index 83b46c6ac5d309721a53b6d92ddff18c3e1f17b2..29e649994f7d356dfc7728aacf87d509d8cef07a 100644 --- a/wax-prosemirror-core/src/plugins/portalPlugin.js +++ b/wax-prosemirror-services/src/PortalService/portalPlugin.js @@ -3,11 +3,12 @@ import { Plugin, PluginKey } from 'prosemirror-state'; const portalPlugin = new PluginKey('portalPlugin'); class ReactNodeView { - constructor(node, view, getPos, decorations, createPortal) { + constructor(node, view, getPos, decorations, createPortal, Component) { this.dom = document.createElement('div'); this.dom.id = 'portalId'; this.dom.classList.add('portal'); + console.log('dddd'); createPortal(this.dom, Component); } @@ -21,18 +22,28 @@ class ReactNodeView { } } -const multipleChoice = ({ createPortal }) => { +const PortalWithNodeView = (createPortal, Component) => { return (theNode, view, getPos, decorations) => - new ReactNodeView(theNode, view, getPos, decorations, createPortal); + new ReactNodeView( + theNode, + view, + getPos, + decorations, + createPortal, + Component, + ); }; export default props => { + const nodeViews = {}; + props.portals.forEach(p => { + nodeViews[p.name] = PortalWithNodeView(props.createPortal, p.component); + }); + return new Plugin({ key: portalPlugin, - state: { - init: (_, state) => { - return props; - }, + props: { + nodeViews, }, }); }; diff --git a/wax-prosemirror-services/src/ShortCutsService/ShortCuts.js b/wax-prosemirror-services/src/ShortCutsService/ShortCuts.js index 5a9ea295a7f1bb666c115b976e6a440ad652144c..17bd379c964ba6de391b01d28e149ce90e6161c2 100644 --- a/wax-prosemirror-services/src/ShortCutsService/ShortCuts.js +++ b/wax-prosemirror-services/src/ShortCutsService/ShortCuts.js @@ -60,6 +60,7 @@ const backSpaceShortCut = (state, dispatch, view) => { }; const pressEnter = (state, dispatch) => { + console.log('enter'); if (state.selection.node && state.selection.node.type.name === 'image') { const { $from, to } = state.selection; diff --git a/wax-prosemirror-services/src/ShortCutsService/ShortCutsService.js b/wax-prosemirror-services/src/ShortCutsService/ShortCutsService.js index f558ae8743c3791e2b36ada70efe09ae412bd51f..9fb87c58f528f17ac4161214ca5bba8d10eed9fa 100644 --- a/wax-prosemirror-services/src/ShortCutsService/ShortCutsService.js +++ b/wax-prosemirror-services/src/ShortCutsService/ShortCutsService.js @@ -1,20 +1,23 @@ -import Service from "../Service"; -import ShortCuts from "./ShortCuts"; +import Service from '../Service'; +import ShortCuts from './ShortCuts'; export default class ShortCutsService extends Service { - name = "ShortCutsService"; + name = 'ShortCutsService'; boot() { - const shortCuts = this.container.get("ShortCuts"); + console.log('boot'); + const shortCuts = this.container.get('ShortCuts'); shortCuts.createShortCuts(); } register() { - const PmPlugins = this.app.PmPlugins; + const { PmPlugins } = this.app; this.container - .bind("ShortCuts") + .bind('ShortCuts') .toDynamicValue(() => { - const { schema: { schema } } = this.app; + const { + schema: { schema }, + } = this.app; return new ShortCuts(PmPlugins, schema); })