feat(embedded-dashboard): Share Switchboard State for Sending Events from Plugins (#21319)

This commit is contained in:
Shubham Sinha 2022-10-10 18:57:43 +05:30 committed by GitHub
parent d1a6f0ebc4
commit 20b9dc8444
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 10 deletions

View File

@ -17,4 +17,7 @@
* under the License.
*/
import Switchboard from './switchboard';
export * from './switchboard';
export default Switchboard;

View File

@ -17,7 +17,7 @@
* under the License.
*/
import { Switchboard } from './switchboard';
import SingletonSwitchboard, { Switchboard } from './switchboard';
type EventHandler = (event: MessageEvent) => void;
@ -114,6 +114,7 @@ describe('comms', () => {
beforeEach(() => {
console.debug = jest.fn(); // silencio bruno
console.error = jest.fn();
});
afterEach(() => {
@ -128,6 +129,30 @@ describe('comms', () => {
expect(sb).toHaveProperty('debugMode');
});
it('singleton', async () => {
SingletonSwitchboard.start();
expect(console.error).toHaveBeenCalledWith(
'[]',
'Switchboard not initialised',
);
SingletonSwitchboard.emit('someEvent', 42);
expect(console.error).toHaveBeenCalledWith(
'[]',
'Switchboard not initialised',
);
await expect(SingletonSwitchboard.get('failing')).rejects.toThrow(
'Switchboard not initialised',
);
SingletonSwitchboard.init({ port: new MessageChannel().port1 });
expect(SingletonSwitchboard).toHaveProperty('name');
expect(SingletonSwitchboard).toHaveProperty('debugMode');
SingletonSwitchboard.init({ port: new MessageChannel().port1 });
expect(console.error).toHaveBeenCalledWith(
'[switchboard]',
'already initialized',
);
});
describe('emit', () => {
it('triggers the method', async () => {
const channel = new MessageChannel();

View File

@ -90,7 +90,7 @@ function isError(message: Message): message is ErrorMessage {
export class Switchboard {
port: MessagePort;
name: string;
name = '';
methods: Record<string, Method<any, unknown>> = {};
@ -99,7 +99,23 @@ export class Switchboard {
debugMode: boolean;
constructor({ port, name = 'switchboard', debug = false }: Params) {
private isInitialised: boolean;
constructor(params?: Params) {
if (!params) {
return;
}
this.init(params);
}
init(params: Params) {
if (this.isInitialised) {
this.logError('already initialized');
return;
}
const { port, name = 'switchboard', debug = false } = params;
this.port = port;
this.name = name;
this.debugMode = debug;
@ -122,6 +138,8 @@ export class Switchboard {
}
}
});
this.isInitialised = true;
}
private async getMethodResult({
@ -178,6 +196,10 @@ export class Switchboard {
*/
get<T = unknown>(method: string, args: unknown = undefined): Promise<T> {
return new Promise((resolve, reject) => {
if (!this.isInitialised) {
reject(new Error('Switchboard not initialised'));
return;
}
// In order to "call a method" on the other side of the port,
// we will send a message with a unique id
const messageId = this.getNewMessageId();
@ -215,6 +237,10 @@ export class Switchboard {
* @param args
*/
emit(method: string, args: unknown = undefined) {
if (!this.isInitialised) {
this.logError('Switchboard not initialised');
return;
}
const message: EmitMessage = {
switchboardAction: Actions.EMIT,
method,
@ -224,6 +250,10 @@ export class Switchboard {
}
start() {
if (!this.isInitialised) {
this.logError('Switchboard not initialised');
return;
}
this.port.start();
}
@ -242,3 +272,5 @@ export class Switchboard {
return `m_${this.name}_${this.incrementor++}`;
}
}
export default new Switchboard();

View File

@ -20,7 +20,7 @@ import React, { lazy, Suspense } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { makeApi, t, logging } from '@superset-ui/core';
import { Switchboard } from '@superset-ui/switchboard';
import Switchboard from '@superset-ui/switchboard';
import { bootstrapData } from 'src/preamble';
import setupClient from 'src/setup/setupClient';
import { RootContextProviders } from 'src/views/RootContextProviders';
@ -176,7 +176,7 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
if (event.data.handshake === 'port transfer' && port) {
log('message port received', event);
const switchboard = new Switchboard({
Switchboard.init({
port,
name: 'superset',
debug: debugMode,
@ -184,7 +184,7 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
let started = false;
switchboard.defineMethod(
Switchboard.defineMethod(
'guestToken',
({ guestToken }: { guestToken: string }) => {
setupGuestClient(guestToken);
@ -195,13 +195,13 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
},
);
switchboard.defineMethod('getScrollSize', embeddedApi.getScrollSize);
switchboard.defineMethod(
Switchboard.defineMethod('getScrollSize', embeddedApi.getScrollSize);
Switchboard.defineMethod(
'getDashboardPermalink',
embeddedApi.getDashboardPermalink,
);
switchboard.defineMethod('getActiveTabs', embeddedApi.getActiveTabs);
switchboard.start();
Switchboard.defineMethod('getActiveTabs', embeddedApi.getActiveTabs);
Switchboard.start();
}
});