From 6cdddb9add9243bd5ece61a96792fd30cc335dbb Mon Sep 17 00:00:00 2001 From: Giannis Kopanas <jkopanas@gmail.com> Date: Fri, 22 Nov 2019 22:58:45 +0200 Subject: [PATCH] feat(services): add services --- editors/editoria/config-overrides.js | 6 +- editors/editoria/jsconfig.json | 5 + editors/editoria/package.json | 3 +- editors/editoria/src/EditorConfig.js | 8 +- editors/editoria/src/Editoria.js | 5 +- package.json | 7 +- wax-prosemirror-components/index.js | 2 +- .../src/components/componentPlugin.js | 28 ----- wax-prosemirror-core/index.js | 1 + wax-prosemirror-core/package.json | 5 +- wax-prosemirror-core/src/Wax.js | 22 +++- wax-prosemirror-core/src/componentPlugin.js | 16 +++ wax-prosemirror-core/src/ioc-react.js | 24 ++++ wax-prosemirror-core/src/ioc.js | 6 + wax-prosemirror-plugins/index.js | 2 + wax-prosemirror-plugins/package.json | 5 +- .../src/LayoutService/Layout.js | 17 +++ .../src/LayoutService/LayoutService.js | 11 ++ .../src/LinkService/LinkPlugin.js | 40 +++++++ .../src/LinkService/LinkService.js | 21 ++++ .../src/LinkService/pmPlugins/find.js | 14 +++ .../src/LinkService/pmPlugins/placeholder.js | 14 +++ wax-prosemirror-plugins/src/Service.js | 9 ++ .../src/overlay/OverlayPlugin.js | 111 ++++++++---------- 24 files changed, 277 insertions(+), 105 deletions(-) create mode 100644 editors/editoria/jsconfig.json delete mode 100644 wax-prosemirror-components/src/components/componentPlugin.js create mode 100644 wax-prosemirror-core/src/componentPlugin.js create mode 100644 wax-prosemirror-core/src/ioc-react.js create mode 100644 wax-prosemirror-core/src/ioc.js create mode 100644 wax-prosemirror-plugins/src/LayoutService/Layout.js create mode 100644 wax-prosemirror-plugins/src/LayoutService/LayoutService.js create mode 100644 wax-prosemirror-plugins/src/LinkService/LinkPlugin.js create mode 100644 wax-prosemirror-plugins/src/LinkService/LinkService.js create mode 100644 wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js create mode 100644 wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js create mode 100644 wax-prosemirror-plugins/src/Service.js diff --git a/editors/editoria/config-overrides.js b/editors/editoria/config-overrides.js index 82c74c17d..e2cf94482 100644 --- a/editors/editoria/config-overrides.js +++ b/editors/editoria/config-overrides.js @@ -12,7 +12,11 @@ module.exports = function override(config, env) { [require("@babel/preset-env"), { modules: false }], require("@babel/preset-react") ], - plugins: [require("@babel/plugin-proposal-class-properties")] + plugins: [ + ["@babel/plugin-proposal-decorators", { legacy: true }], + "babel-plugin-parameter-decorator", + ["@babel/plugin-proposal-class-properties", { loose: true }] + ] } }, { diff --git a/editors/editoria/jsconfig.json b/editors/editoria/jsconfig.json new file mode 100644 index 000000000..504cd646e --- /dev/null +++ b/editors/editoria/jsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "experimentalDecorators": true + } +} diff --git a/editors/editoria/package.json b/editors/editoria/package.json index 84d3efed8..820265276 100644 --- a/editors/editoria/package.json +++ b/editors/editoria/package.json @@ -13,7 +13,8 @@ "wax-prosemirror-core": "^0.0.3", "wax-prosemirror-layouts": "^0.0.3", "wax-prosemirror-schema": "^0.0.3", - "wax-prosemirror-themes": "^0.0.3" + "wax-prosemirror-themes": "^0.0.3", + "babel-plugin-parameter-decorator": "1.0.12" }, "scripts": { "start": "react-app-rewired start", diff --git a/editors/editoria/src/EditorConfig.js b/editors/editoria/src/EditorConfig.js index e0d225b71..4dbf29f8b 100644 --- a/editors/editoria/src/EditorConfig.js +++ b/editors/editoria/src/EditorConfig.js @@ -31,7 +31,9 @@ import { LinkToolTipPlugin, FindAndReplacePlugin, TrackChangePlugin, - MenuBarPlugin + MenuBarPlugin, + LinkService, + LayoutService } from "wax-prosemirror-plugins"; import { MainMenuBar, SideMenuBar } from "wax-prosemirror-components"; @@ -98,7 +100,9 @@ const plugins = [ }) ]; +const services = [new LayoutService(), new LinkService()]; + // Add Rules const rules = [emDash, ellipsis]; -export { schema, keys, plugins, rules }; +export { schema, keys, plugins, rules, services }; diff --git a/editors/editoria/src/Editoria.js b/editors/editoria/src/Editoria.js index 594b9b630..dd3b7e463 100644 --- a/editors/editoria/src/Editoria.js +++ b/editors/editoria/src/Editoria.js @@ -3,7 +3,7 @@ import styled, { createGlobalStyle } from "styled-components"; import { setLayout } from "wax-prosemirror-core"; -import { schema, keys, plugins, rules } from "./EditorConfig"; +import { schema, keys, plugins, rules, services } from "./EditorConfig"; import text from "./text"; @@ -11,7 +11,8 @@ const options = { schema, plugins, keys, - rules + rules, + services }; const GlobalStyle = createGlobalStyle` diff --git a/package.json b/package.json index f58069cda..090c5c4d7 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "version": "0.0.1", "main": "index.js", "author": "Collaborative Knowledge Foundation", - "description": - "Monorepo for wax-prosemirror, its components and its integrations", + "description": "Monorepo for wax-prosemirror, its components and its integrations", "repository": { "type": "git", "url": "git@gitlab.coko.foundation:wax/wax-prosemirror.git" @@ -13,8 +12,7 @@ "private": true, "scripts": { "bootstrap": "lerna bootstrap --no-ci --hoist", - "clean": - "yarn run clean:artifacts && yarn run clean:packages && yarn run clean:root", + "clean": "yarn run clean:artifacts && yarn run clean:packages && yarn run clean:root", "clean:artifacts": "lerna run clean --parallel", "clean:packages": "lerna clean --yes", "clean:root": "rm -rf node_modules", @@ -26,6 +24,7 @@ "dependencies": {}, "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-decorators": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "css-loader": "^0.28.11", diff --git a/wax-prosemirror-components/index.js b/wax-prosemirror-components/index.js index 57975b195..64873c033 100644 --- a/wax-prosemirror-components/index.js +++ b/wax-prosemirror-components/index.js @@ -1,5 +1,5 @@ export { default as MainMenuBar } from "./src/mainMenuBar/MainMenuBar"; export { default as SideMenuBar } from "./src/sideMenuBar/SideMenuBar"; export { default as InfoArea } from "./src/components/infoArea/InfoArea"; -export { default as componentPlugin } from "./src/components/componentPlugin"; +export { default as componentPlugin } from "wax-prosemirror-core/src/componentPlugin"; export { default as Overlay } from "./src/components/Overlay"; diff --git a/wax-prosemirror-components/src/components/componentPlugin.js b/wax-prosemirror-components/src/components/componentPlugin.js deleted file mode 100644 index c9d2ba14b..000000000 --- a/wax-prosemirror-components/src/components/componentPlugin.js +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; -import WaxContext from "wax-prosemirror-core/src/helpers/WaxContext"; - -const ComponentPlugin = renderArea => props => ( - <WaxContext.Consumer> - {context => { - const { state = { plugins: [] } } = context.view; - const pluginComponent = state.plugins.map(plugin => { - if ( - state[plugin.key] && - state[plugin.key].renderArea === renderArea && - state[plugin.key].component - ) { - const Component = state[plugin.key].component; - return ( - <Component key={plugin.key} view={context.view} state={state} /> - ); - } - - return null; - }); - - return pluginComponent; - }} - </WaxContext.Consumer> -); - -export default ComponentPlugin; diff --git a/wax-prosemirror-core/index.js b/wax-prosemirror-core/index.js index a9e4bb31a..47330de98 100644 --- a/wax-prosemirror-core/index.js +++ b/wax-prosemirror-core/index.js @@ -3,3 +3,4 @@ export { default as CreateSchema } from "./src/config/classes/CreateSchema"; export { default as setLayout } from "./src/helpers/setLayout"; export { default as CreateShortCuts } from "./src/config/classes/CreateShortCuts"; export { default as WaxContext } from "./src/helpers/WaxContext"; +export { default as Container } from "./src/ioc"; diff --git a/wax-prosemirror-core/package.json b/wax-prosemirror-core/package.json index ceb04f8d0..45b97b43b 100644 --- a/wax-prosemirror-core/package.json +++ b/wax-prosemirror-core/package.json @@ -23,7 +23,10 @@ "prosemirror-view": "^1.13.4", "react": "^16.8.6", "react-dom": "^16.8.6", - "styled-components": "^4.2.0" + "styled-components": "^4.2.0", + "inversify": "^5.0.1", + "inversify-inject-decorators": "^3.1.0", + "reflect-metadata": "^0.1.13" }, "devDependencies": { "mocha": "^3.4.2", diff --git a/wax-prosemirror-core/src/Wax.js b/wax-prosemirror-core/src/Wax.js index e1657c505..9da883db8 100644 --- a/wax-prosemirror-core/src/Wax.js +++ b/wax-prosemirror-core/src/Wax.js @@ -1,11 +1,13 @@ import React, { Component } from "react"; +import WaxProvider from "./ioc-react"; +import container from "./ioc"; + import debounce from "lodash/debounce"; import styled from "styled-components"; import { DOMParser, DOMSerializer } from "prosemirror-model"; import { DefaultLayout } from "wax-prosemirror-layouts"; -import WaxContext from "./helpers/WaxContext"; import WaxView from "./WaxView"; import defaultPlugins from "./config/defaultPlugins"; import placeholder from "./config/plugins/placeholder"; @@ -42,7 +44,7 @@ const LayoutWrapper = styled.div` class Wax extends Component { componentWillMount() { const { value, onChange, options } = this.props; - const { schema, plugins, keys, rules } = options; + const { schema, plugins, keys, rules, services } = options; const WaxOnchange = onChange ? onChange : value => true; const WaxShortCuts = keys @@ -61,6 +63,12 @@ class Wax extends Component { WaxRules ]); + services.map(plugin => { + if (plugin.register) { + plugin.register(); + } + }); + this.WaxOptions = { schema, plugins: finalPlugins @@ -70,6 +78,12 @@ class Wax extends Component { const serialize = serializer(schema); this.WaxOptions.doc = parse(editorContent); + services.map(plugin => { + if (plugin.register) { + plugin.boot(); + } + }); + this.onChange = debounce( value => { WaxOnchange(serialize(value)); @@ -115,9 +129,9 @@ class Wax extends Component { user={user} > {({ view, editor }) => ( - <WaxContext.Provider value={{ view }}> + <WaxProvider view={view} container={container}> <WaxRender editor={editor} /> - </WaxContext.Provider> + </WaxProvider> )} </WaxView> </LayoutWrapper> diff --git a/wax-prosemirror-core/src/componentPlugin.js b/wax-prosemirror-core/src/componentPlugin.js new file mode 100644 index 000000000..8a44c7a93 --- /dev/null +++ b/wax-prosemirror-core/src/componentPlugin.js @@ -0,0 +1,16 @@ +import React from "react"; +import { useInjection } from "./ioc-react"; + +const ComponentPlugin = renderArea => props => { + const Layout = useInjection("Layout"); + console.log(Layout); + const { Component } = Layout.render(renderArea); + + return Component ? <Component renderArea={renderArea} /> : null; + return Component.map(Component => + Component.renderArea === renderArea ? ( + <Component.component renderArea={renderArea} /> + ) : null + ); +}; +export default ComponentPlugin; diff --git a/wax-prosemirror-core/src/ioc-react.js b/wax-prosemirror-core/src/ioc-react.js new file mode 100644 index 000000000..8f82eec3d --- /dev/null +++ b/wax-prosemirror-core/src/ioc-react.js @@ -0,0 +1,24 @@ +import React, { useContext } from "react"; + +const WaxContext = React.createContext({ view: null, container: null }); + +export default props => { + console.log(props); + return ( + <WaxContext.Provider + value={{ container: props.container, view: props.view }} + > + {props.children} + </WaxContext.Provider> + ); +}; + +export function useInjection(identifier) { + const { container } = useContext(WaxContext); + + if (!container) { + throw new Error(); + } + + return container.isBound(identifier) ? container.get(identifier) : null; +} diff --git a/wax-prosemirror-core/src/ioc.js b/wax-prosemirror-core/src/ioc.js new file mode 100644 index 000000000..5e07d5aee --- /dev/null +++ b/wax-prosemirror-core/src/ioc.js @@ -0,0 +1,6 @@ +import { Container } from "inversify"; +import "reflect-metadata"; + +const container = new Container(); + +export default container; diff --git a/wax-prosemirror-plugins/index.js b/wax-prosemirror-plugins/index.js index 47d507af1..07e822af8 100644 --- a/wax-prosemirror-plugins/index.js +++ b/wax-prosemirror-plugins/index.js @@ -2,3 +2,5 @@ export { default as TrackChangePlugin } from "./src/trackChanges/TrackChangePlug export { default as FindAndReplacePlugin } from "./src/FindAndReplacePlugin"; export { default as MenuBarPlugin } from "./src/menuBar/MenuBarPlugin"; export { default as OverlayPlugin } from "./src/overlay/OverlayPlugin"; +export { default as LayoutService } from "./src/LayoutService/LayoutService"; +export { default as LinkService } from "./src/LinkService/LinkService"; diff --git a/wax-prosemirror-plugins/package.json b/wax-prosemirror-plugins/package.json index eedc5ee50..76421fc64 100644 --- a/wax-prosemirror-plugins/package.json +++ b/wax-prosemirror-plugins/package.json @@ -10,6 +10,9 @@ }, "dependencies": { "prosemirror-state": "^1.2.2", - "prosemirror-view": "^1.13.1" + "prosemirror-view": "^1.13.1", + "inversify": "^5.0.1", + "inversify-inject-decorators": "^3.1.0", + "reflect-metadata": "^0.1.13" } } diff --git a/wax-prosemirror-plugins/src/LayoutService/Layout.js b/wax-prosemirror-plugins/src/LayoutService/Layout.js new file mode 100644 index 000000000..f88b2244e --- /dev/null +++ b/wax-prosemirror-plugins/src/LayoutService/Layout.js @@ -0,0 +1,17 @@ +import { injectable, multiInject } from "inversify"; + +@injectable() +export default class Layout { + constructor() { + this.components = new Map(); + } + + addComponent(renderArea, component) { + this.components.set(renderArea, component); + return this; + } + + render(renderArea) { + return { Component: this.components.get(renderArea) }; + } +} diff --git a/wax-prosemirror-plugins/src/LayoutService/LayoutService.js b/wax-prosemirror-plugins/src/LayoutService/LayoutService.js new file mode 100644 index 000000000..b98b5fb9e --- /dev/null +++ b/wax-prosemirror-plugins/src/LayoutService/LayoutService.js @@ -0,0 +1,11 @@ +import Service from "../Service"; +import Layout from "./Layout"; +export default class LayoutService extends Service { + name = "LayoutService"; + register() { + this.container + .bind("Layout") + .to(Layout) + .inSingletonScope(); + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js b/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js new file mode 100644 index 000000000..206e598df --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js @@ -0,0 +1,40 @@ +import React from "react"; +import { injectable, multiInject, inject, named } from "inversify"; + +const Component1 = props => <div>{props.renderArea}</div>; +const Component2 = props => <div>{props.renderArea}</div>; + +@injectable() +export default class LinkPlugin { + items = [ + { + link: "1", + link2: "3" + }, + { + link: "2", + link2: "4" + } + ]; + plugins = []; + + constructor( + @inject("Layout") layout, + @inject("findPlugin") find, + @inject("placeholderPlugin") placeholder + ) { + this.find = find; + this.placeholder = placeholder; + + //console.log(this.find, this.placeholder); + layout + .addComponent("topBar", Component2) + .addComponent("leftSideBar", Component1); + + this.initPlugins(); + } + + initPlugins() { + this.plugins = [this.placeholder(this.items[1]), this.find("s")]; + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/LinkService.js b/wax-prosemirror-plugins/src/LinkService/LinkService.js new file mode 100644 index 000000000..6d2900ab0 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/LinkService.js @@ -0,0 +1,21 @@ +import LinkPlugin from "./LinkPlugin"; +import Service from "../Service"; +import find from "./pmPlugins/find"; +import placeholder from "./pmPlugins/placeholder"; + +export default class myLinkPluginService extends Service { + name = "LinkPlugin"; + + boot() { + const test = this.container.get("LinkPlugin"); + console.log(test); + } + + register() { + this.container.bind(this.name).to(LinkPlugin); + + this.container.bind("findPlugin").toFactory(find); + + this.container.bind("placeholderPlugin").toFactory(placeholder); + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js b/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js new file mode 100644 index 000000000..4a6d8bbb5 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js @@ -0,0 +1,14 @@ +import { Plugin, PluginKey } from "prosemirror-state"; +export const findLink = new PluginKey("findLink"); + +export default items => { + return () => + new Plugin({ + key: findLink, + state: { + init() { + return items; + } + } + }); +}; diff --git a/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js b/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js new file mode 100644 index 000000000..6ca4468e4 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js @@ -0,0 +1,14 @@ +import { Plugin, PluginKey } from "prosemirror-state"; +export const placeholderLink = new PluginKey("placeholderLink"); + +export default items => { + return () => + new Plugin({ + key: placeholderLink, + state: { + init() { + return items; + } + } + }); +}; diff --git a/wax-prosemirror-plugins/src/Service.js b/wax-prosemirror-plugins/src/Service.js new file mode 100644 index 000000000..d3c2e4603 --- /dev/null +++ b/wax-prosemirror-plugins/src/Service.js @@ -0,0 +1,9 @@ +import { Container } from "wax-prosemirror-core"; + +export default class Service { + constructor() { + this.container = Container; + } + + boot() {} +} diff --git a/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js b/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js index deda62777..f923f2906 100644 --- a/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js +++ b/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js @@ -27,63 +27,54 @@ const OverlayPlugin = args => { export default OverlayPlugin; - -reactComponent - -overlayPlugin position - -linkPlugin showhide - - -linkPlugin = createplugin (reactComponent, overlay) - - - -const createPlugin = (reactComponent, overlayPlugin) => { - - return new Plugin ({ - key, - state, - view, - }) -} - -createPlugin = () => class { - name: "test", - renderArea, - component: () => {}, - itemsMenus: [], - plugins: [plugin, plugin] -} - - - -class createPlugin { - constructor() { - this.name - this.plugins.push(overlayPlugin(Component, showCommand)) - } - plugins () { return []} -} - - -class waxPlugin { - constructor() { - this.name - - } - - createPlugin () { - - } -} - -class linkPlugin extends waxPlugin { - component: - renderArea: - showCommand: - itemsMenus: - -} - -new(OverlayPlugin) \ No newline at end of file +// reactComponent + +// overlayPlugin position + +// linkPlugin showhide + +// linkPlugin = createplugin(reactComponent, overlay); + +// const createPlugin = (reactComponent, overlayPlugin) => { +// return new Plugin({ +// key, +// state, +// view +// }); +// }; + +// createPlugin = () => class { +// name: "test", +// renderArea, +// component: () => {}, +// itemsMenus: [], +// plugins: [plugin, plugin] +// } + +// class createPlugin { +// constructor() { +// this.name; +// this.plugins.push(overlayPlugin(Component, showCommand)); +// } +// plugins() { +// return []; +// } +// } + +// class waxPlugin { +// constructor() { +// this.name; +// } + +// createPlugin() {} +// } + +// class linkPlugin extends waxPlugin { +// component: +// renderArea: +// showCommand: +// itemsMenus: + +// } + +// new(OverlayPlugin) -- GitLab