From bfe9b80626f619d9570177482fd76b6fef97c6be Mon Sep 17 00:00:00 2001 From: Giannis kopanas <jkopanas@gmail.com> Date: Thu, 15 Apr 2021 12:02:07 +0300 Subject: [PATCH] fix(core): use portals --- .../MultipleChoiceQuestionService.js | 11 ++++--- wax-prosemirror-core/src/Application.js | 4 +++ wax-prosemirror-core/src/PortalContext.js | 11 +++---- wax-prosemirror-core/src/Wax.js | 8 ++--- wax-prosemirror-core/src/WaxView.js | 6 ++++ wax-prosemirror-core/src/useWaxOptions.js | 5 ---- .../src/PortalService/PortalService.js | 29 ++++++++++++++----- .../src/PortalService/Portals.js | 14 +++++++++ .../components/PortalComponent.js | 26 ++++++++++------- .../src/PortalService}/portalPlugin.js | 25 +++++++++++----- .../src/ShortCutsService/ShortCuts.js | 1 + .../src/ShortCutsService/ShortCutsService.js | 17 ++++++----- 12 files changed, 106 insertions(+), 51 deletions(-) create mode 100644 wax-prosemirror-services/src/PortalService/Portals.js rename {wax-prosemirror-core/src/plugins => wax-prosemirror-services/src/PortalService}/portalPlugin.js (54%) diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js index 6a259507f..54cc4a9cd 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 02ed53193..63b621a86 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 0de864cce..23e5ca9a1 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 d54aa7fd1..222961eb8 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 1a3fbdb32..309421105 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 4f41a14cd..41d0fbb69 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 5dc677744..a8d3c629d 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 000000000..133672fd2 --- /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 3bb081801..7ea44cdd7 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 83b46c6ac..29e649994 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 5a9ea295a..17bd379c9 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 f558ae874..9fb87c58f 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); }) -- GitLab