From 2772584fe277c40825420bcbd65a9f7057649df4 Mon Sep 17 00:00:00 2001 From: Malek Date: Sun, 29 Jul 2018 08:29:14 +0300 Subject: Add pubsub, Fix loader in sdc Issue-ID: SDC-1564 Change-Id: I562c9e3137c36bf0aac603eb64578b741c112b5f Signed-off-by: Malek --- .../src/main/frontend/package.json | 2 + workflow-designer-ui/src/main/frontend/src/App.js | 14 ++- .../src/main/frontend/src/index.js | 6 +- .../main/frontend/src/shared/pubsub/base-pubsub.ts | 127 +++++++++++++++++++++ .../frontend/src/shared/pubsub/plugin-pubsub.ts | 30 +++++ .../src/main/frontend/tsconfig.json | 12 ++ .../src/main/frontend/webpack.config.js | 7 +- workflow-designer-ui/src/main/frontend/yarn.lock | 21 +++- 8 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 workflow-designer-ui/src/main/frontend/src/shared/pubsub/base-pubsub.ts create mode 100644 workflow-designer-ui/src/main/frontend/src/shared/pubsub/plugin-pubsub.ts create mode 100644 workflow-designer-ui/src/main/frontend/tsconfig.json diff --git a/workflow-designer-ui/src/main/frontend/package.json b/workflow-designer-ui/src/main/frontend/package.json index 911eb629..dc2c229c 100644 --- a/workflow-designer-ui/src/main/frontend/package.json +++ b/workflow-designer-ui/src/main/frontend/package.json @@ -50,6 +50,7 @@ "validator": "^10.2.0" }, "devDependencies": { + "awesome-typescript-loader": "^5.2.0", "babel-core": "^6.24.0", "babel-eslint": "^8.2.1", "babel-jest": "^22.1.0", @@ -83,6 +84,7 @@ "react-test-renderer": "^16.4.1", "sass-loader": "^6.0.6", "source-map-loader": "^0.1.5", + "typescript": "^2.9.2", "uglifyjs-webpack-plugin": "^1.1.6", "webpack": "^4.5.0", "webpack-api-mocker": "^1.4.3", diff --git a/workflow-designer-ui/src/main/frontend/src/App.js b/workflow-designer-ui/src/main/frontend/src/App.js index f780c8ed..7b46fe48 100644 --- a/workflow-designer-ui/src/main/frontend/src/App.js +++ b/workflow-designer-ui/src/main/frontend/src/App.js @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { hot } from 'react-hot-loader'; import React, { Component } from 'react'; import { Route } from 'react-router-dom'; +import { PluginPubSub } from 'shared/pubsub/plugin-pubsub'; import 'resources/scss/style.scss'; import 'bpmn-js-properties-panel/styles/properties.less'; import { routes } from './routes'; @@ -30,8 +32,16 @@ const RouteWithSubRoutes = route => ( ); class App extends Component { - constructor(props) { - super(props); + componentDidMount() { + const searchParams = new URLSearchParams(location.search); + const eventsClientId = searchParams.get('eventsClientId'); + const parentUrl = searchParams.get('parentUrl'); + + if (eventsClientId && parentUrl) { + const client = new PluginPubSub(eventsClientId, parentUrl); + + client.notify('READY'); + } } render() { diff --git a/workflow-designer-ui/src/main/frontend/src/index.js b/workflow-designer-ui/src/main/frontend/src/index.js index 9dfe6378..d33f47cb 100644 --- a/workflow-designer-ui/src/main/frontend/src/index.js +++ b/workflow-designer-ui/src/main/frontend/src/index.js @@ -17,7 +17,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; -import { HashRouter } from 'react-router-dom'; +import { BrowserRouter } from 'react-router-dom'; import Notifications from 'shared/notifications/Notifications'; import Loader from 'shared/loader/Loader'; @@ -30,14 +30,14 @@ ReactDOM.render( - +
-
+
, document.getElementById('root') diff --git a/workflow-designer-ui/src/main/frontend/src/shared/pubsub/base-pubsub.ts b/workflow-designer-ui/src/main/frontend/src/shared/pubsub/base-pubsub.ts new file mode 100644 index 00000000..41e8039d --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/src/shared/pubsub/base-pubsub.ts @@ -0,0 +1,127 @@ +declare const window: Window; + +export class BasePubSub { + + subscribers: Map; + eventsCallbacks: Array; + clientId: string; + eventsToWait: Map>; + lastEventNotified: string; + + constructor(pluginId: string) { + this.subscribers = new Map(); + this.eventsCallbacks = []; + this.eventsToWait = new Map>(); + this.clientId = pluginId; + this.lastEventNotified = ""; + this.onMessage = this.onMessage.bind(this); + + window.addEventListener("message", this.onMessage); + } + + public register(subscriberId: string, subscriberWindow: Window, subscriberUrl: string) { + const subscriber = { + window: subscriberWindow, + locationUrl: subscriberUrl || subscriberWindow.location.href + } as ISubscriber; + + this.subscribers.set(subscriberId, subscriber); + } + + public unregister(subscriberId: string) { + this.subscribers.delete(subscriberId); + } + + public on(callback: Function) { + let functionExists = this.eventsCallbacks.find((func: Function) => { + return callback.toString() == func.toString() + }); + + if (!functionExists) { + this.eventsCallbacks.push(callback); + } + } + + public off(callback: Function) { + let index = this.eventsCallbacks.indexOf(callback); + this.eventsCallbacks.splice(index, 1) + } + + public notify(eventType:string, eventData?:any) { + let eventObj = { + type: eventType, + data: eventData, + originId: this.clientId + } as IPubSubEvent; + + this.subscribers.forEach( (subscriber: ISubscriber, subscriberId: string) => { + subscriber.window.postMessage(eventObj, subscriber.locationUrl); + }); + + this.lastEventNotified = eventType; + + return { + subscribe: function(callbackFn) { + + if(this.subscribers.size !== 0) { + let subscribersToNotify = Array.from(this.subscribers.keys()); + + const checkNotifyComplete = (subscriberId: string) => { + + let index = subscribersToNotify.indexOf(subscriberId); + subscribersToNotify.splice(index, 1); + + if (subscribersToNotify.length === 0) { + callbackFn(); + } + }; + + this.subscribers.forEach((subscriber: ISubscriber, subscriberId: string) => { + if (this.eventsToWait.has(subscriberId) && this.eventsToWait.get(subscriberId).indexOf(eventType) !== -1) { + + const actionCompletedFunction = (eventData, subId = subscriberId) => { + if (eventData.type == "ACTION_COMPLETED") { + checkNotifyComplete(subId); + } + this.off(actionCompletedFunction); + + }; + this.on(actionCompletedFunction); + } + else { + checkNotifyComplete(subscriberId); + } + }); + } + else { + callbackFn(); + } + }.bind(this) + } + } + + public isWaitingForEvent(eventName: string) : boolean { + return Array.from(this.eventsToWait.values()).some((eventsList: Array) => + eventsList.indexOf(eventName) !== -1 + ); + } + + protected onMessage(event: any) { + if (this.subscribers.has(event.data.originId)) { + this.eventsCallbacks.forEach((callback: Function) => { + callback(event.data, event); + }) + } + } +} + +export interface IPubSubEvent { + type: string; + originId: string; + data: any; +} + +export interface ISubscriber { + window: Window; + locationUrl: string; +} diff --git a/workflow-designer-ui/src/main/frontend/src/shared/pubsub/plugin-pubsub.ts b/workflow-designer-ui/src/main/frontend/src/shared/pubsub/plugin-pubsub.ts new file mode 100644 index 00000000..8f99e659 --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/src/shared/pubsub/plugin-pubsub.ts @@ -0,0 +1,30 @@ +import {BasePubSub} from 'shared/pubsub/base-pubsub'; + +declare const window: Window; + +export class PluginPubSub extends BasePubSub { + + + constructor(pluginId: string, parentUrl: string, eventsToWait?: Array) { + super(pluginId); + this.register('sdc-hub', window.parent, parentUrl); + this.subscribe(eventsToWait); + } + + public subscribe(eventsToWait?: Array) { + const registerData = { + pluginId: this.clientId, + eventsToWait: eventsToWait || [] + }; + + this.notify('PLUGIN_REGISTER', registerData); + } + + public unsubscribe() { + const unregisterData = { + pluginId: this.clientId + }; + + this.notify('PLUGIN_UNREGISTER', unregisterData); + } +} diff --git a/workflow-designer-ui/src/main/frontend/tsconfig.json b/workflow-designer-ui/src/main/frontend/tsconfig.json new file mode 100644 index 00000000..a3bc367f --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict" : false, + "noImplicitAny": false, + "outDir": "./dist/", + "module": "es6", + "target": "es5", + "jsx": "react", + "lib": ["es5", "es6", "dom"], + "allowJs": true + } +} diff --git a/workflow-designer-ui/src/main/frontend/webpack.config.js b/workflow-designer-ui/src/main/frontend/webpack.config.js index c281bbab..9038b70a 100644 --- a/workflow-designer-ui/src/main/frontend/webpack.config.js +++ b/workflow-designer-ui/src/main/frontend/webpack.config.js @@ -42,7 +42,7 @@ module.exports = (env, argv) => { devtool: DEV ? 'eval-source-map' : 'none', resolve: { modules: modulePath, - extensions: ['.js', '.json', '.css', '.scss', '.jsx'], + extensions: ['.js', '.json', '.css', '.scss', '.jsx', '.ts'], alias: { wfapp: path.resolve(__dirname, 'src/'), features: path.resolve(__dirname, 'src/features'), @@ -122,6 +122,11 @@ module.exports = (env, argv) => { { test: /\.(bpmn|xml)$/, loader: 'raw-loader' + }, + { + test: /\.ts|\.tsx$/, + loader: ['babel-loader', 'awesome-typescript-loader'], + include: srcPath } ] }, diff --git a/workflow-designer-ui/src/main/frontend/yarn.lock b/workflow-designer-ui/src/main/frontend/yarn.lock index 2d73ab95..7e31f62b 100644 --- a/workflow-designer-ui/src/main/frontend/yarn.lock +++ b/workflow-designer-ui/src/main/frontend/yarn.lock @@ -921,6 +921,19 @@ autoprefixer@^7.2.6: postcss "^6.0.17" postcss-value-parser "^3.2.3" +awesome-typescript-loader@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.0.tgz#d7bccf4823c45096ec24da4c12a1507d276ba15a" + dependencies: + chalk "^2.4.1" + enhanced-resolve "^4.0.0" + loader-utils "^1.1.0" + lodash "^4.17.5" + micromatch "^3.1.9" + mkdirp "^0.5.1" + source-map-support "^0.5.3" + webpack-log "^1.2.0" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -10729,7 +10742,7 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.0: +source-map-support@^0.5.0, source-map-support@^0.5.3: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" dependencies: @@ -11382,6 +11395,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" +typescript@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + ua-parser-js@^0.7.18: version "0.7.18" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" @@ -11976,7 +11993,7 @@ webpack-hot-middleware@^2.22.1: querystring "^0.2.0" strip-ansi "^3.0.0" -webpack-log@^1.0.1, webpack-log@^1.1.2: +webpack-log@^1.0.1, webpack-log@^1.1.2, webpack-log@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" dependencies: -- cgit 1.2.3-korg