mirror of
https://github.com/apache/superset.git
synced 2024-09-06 22:07:34 -04:00
feat(embedded-dashboard): Share Switchboard State for Sending Events from Plugins (#21319)
This commit is contained in:
parent
d1a6f0ebc4
commit
20b9dc8444
@ -17,4 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Switchboard from './switchboard';
|
||||||
|
|
||||||
export * from './switchboard';
|
export * from './switchboard';
|
||||||
|
export default Switchboard;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Switchboard } from './switchboard';
|
import SingletonSwitchboard, { Switchboard } from './switchboard';
|
||||||
|
|
||||||
type EventHandler = (event: MessageEvent) => void;
|
type EventHandler = (event: MessageEvent) => void;
|
||||||
|
|
||||||
@ -114,6 +114,7 @@ describe('comms', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
console.debug = jest.fn(); // silencio bruno
|
console.debug = jest.fn(); // silencio bruno
|
||||||
|
console.error = jest.fn();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -128,6 +129,30 @@ describe('comms', () => {
|
|||||||
expect(sb).toHaveProperty('debugMode');
|
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', () => {
|
describe('emit', () => {
|
||||||
it('triggers the method', async () => {
|
it('triggers the method', async () => {
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
|
@ -90,7 +90,7 @@ function isError(message: Message): message is ErrorMessage {
|
|||||||
export class Switchboard {
|
export class Switchboard {
|
||||||
port: MessagePort;
|
port: MessagePort;
|
||||||
|
|
||||||
name: string;
|
name = '';
|
||||||
|
|
||||||
methods: Record<string, Method<any, unknown>> = {};
|
methods: Record<string, Method<any, unknown>> = {};
|
||||||
|
|
||||||
@ -99,7 +99,23 @@ export class Switchboard {
|
|||||||
|
|
||||||
debugMode: boolean;
|
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.port = port;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.debugMode = debug;
|
this.debugMode = debug;
|
||||||
@ -122,6 +138,8 @@ export class Switchboard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.isInitialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getMethodResult({
|
private async getMethodResult({
|
||||||
@ -178,6 +196,10 @@ export class Switchboard {
|
|||||||
*/
|
*/
|
||||||
get<T = unknown>(method: string, args: unknown = undefined): Promise<T> {
|
get<T = unknown>(method: string, args: unknown = undefined): Promise<T> {
|
||||||
return new Promise((resolve, reject) => {
|
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,
|
// In order to "call a method" on the other side of the port,
|
||||||
// we will send a message with a unique id
|
// we will send a message with a unique id
|
||||||
const messageId = this.getNewMessageId();
|
const messageId = this.getNewMessageId();
|
||||||
@ -215,6 +237,10 @@ export class Switchboard {
|
|||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
emit(method: string, args: unknown = undefined) {
|
emit(method: string, args: unknown = undefined) {
|
||||||
|
if (!this.isInitialised) {
|
||||||
|
this.logError('Switchboard not initialised');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const message: EmitMessage = {
|
const message: EmitMessage = {
|
||||||
switchboardAction: Actions.EMIT,
|
switchboardAction: Actions.EMIT,
|
||||||
method,
|
method,
|
||||||
@ -224,6 +250,10 @@ export class Switchboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
if (!this.isInitialised) {
|
||||||
|
this.logError('Switchboard not initialised');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.port.start();
|
this.port.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,3 +272,5 @@ export class Switchboard {
|
|||||||
return `m_${this.name}_${this.incrementor++}`;
|
return `m_${this.name}_${this.incrementor++}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default new Switchboard();
|
||||||
|
@ -20,7 +20,7 @@ import React, { lazy, Suspense } from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { BrowserRouter as Router, Route } from 'react-router-dom';
|
import { BrowserRouter as Router, Route } from 'react-router-dom';
|
||||||
import { makeApi, t, logging } from '@superset-ui/core';
|
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 { bootstrapData } from 'src/preamble';
|
||||||
import setupClient from 'src/setup/setupClient';
|
import setupClient from 'src/setup/setupClient';
|
||||||
import { RootContextProviders } from 'src/views/RootContextProviders';
|
import { RootContextProviders } from 'src/views/RootContextProviders';
|
||||||
@ -176,7 +176,7 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
|
|||||||
if (event.data.handshake === 'port transfer' && port) {
|
if (event.data.handshake === 'port transfer' && port) {
|
||||||
log('message port received', event);
|
log('message port received', event);
|
||||||
|
|
||||||
const switchboard = new Switchboard({
|
Switchboard.init({
|
||||||
port,
|
port,
|
||||||
name: 'superset',
|
name: 'superset',
|
||||||
debug: debugMode,
|
debug: debugMode,
|
||||||
@ -184,7 +184,7 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
|
|||||||
|
|
||||||
let started = false;
|
let started = false;
|
||||||
|
|
||||||
switchboard.defineMethod(
|
Switchboard.defineMethod(
|
||||||
'guestToken',
|
'guestToken',
|
||||||
({ guestToken }: { guestToken: string }) => {
|
({ guestToken }: { guestToken: string }) => {
|
||||||
setupGuestClient(guestToken);
|
setupGuestClient(guestToken);
|
||||||
@ -195,13 +195,13 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
switchboard.defineMethod('getScrollSize', embeddedApi.getScrollSize);
|
Switchboard.defineMethod('getScrollSize', embeddedApi.getScrollSize);
|
||||||
switchboard.defineMethod(
|
Switchboard.defineMethod(
|
||||||
'getDashboardPermalink',
|
'getDashboardPermalink',
|
||||||
embeddedApi.getDashboardPermalink,
|
embeddedApi.getDashboardPermalink,
|
||||||
);
|
);
|
||||||
switchboard.defineMethod('getActiveTabs', embeddedApi.getActiveTabs);
|
Switchboard.defineMethod('getActiveTabs', embeddedApi.getActiveTabs);
|
||||||
switchboard.start();
|
Switchboard.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user