front/core: add plugin api hooks and output for widgets
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { ComponentType } from 'react';
|
||||
import { PluginOutput, RoutePath, RouteOptions } from './types';
|
||||
import { IconComponent } from '../types';
|
||||
import { Widget } from '../widgetView/types';
|
||||
|
||||
export type PluginConfig = {
|
||||
id: string;
|
||||
@@ -10,6 +11,7 @@ export type PluginConfig = {
|
||||
export type PluginHooks = {
|
||||
router: RouterHooks;
|
||||
entityPage: EntityPageHooks;
|
||||
widgets: WidgetHooks;
|
||||
};
|
||||
|
||||
export type RouterHooks = {
|
||||
@@ -41,6 +43,10 @@ export type EntityPageHooks = {
|
||||
): void;
|
||||
};
|
||||
|
||||
export type WidgetHooks = {
|
||||
add(widget: Widget): void;
|
||||
};
|
||||
|
||||
export const registerSymbol = Symbol('plugin-register');
|
||||
export const outputSymbol = Symbol('plugin-output');
|
||||
|
||||
@@ -98,6 +104,11 @@ export default class Plugin {
|
||||
});
|
||||
},
|
||||
},
|
||||
widgets: {
|
||||
add(widget: Widget) {
|
||||
outputs.push({ type: 'widget', widget });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.storedOutput = outputs;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ComponentType } from 'react';
|
||||
import { IconComponent } from '../types';
|
||||
import { Widget } from '../widgetView/types';
|
||||
|
||||
export type RouteOptions = {
|
||||
// Whether the route path must match exactly, defaults to true.
|
||||
@@ -22,6 +23,11 @@ export type RedirectRouteOutput = {
|
||||
options?: RouteOptions;
|
||||
};
|
||||
|
||||
export type WidgetOutput = {
|
||||
type: 'widget';
|
||||
widget: Widget;
|
||||
};
|
||||
|
||||
export type EntityPageViewRouteOutput = {
|
||||
type: 'entity-page-view-route';
|
||||
path: RoutePath;
|
||||
@@ -39,5 +45,6 @@ export type EntityPageNavItemOutput = {
|
||||
export type PluginOutput =
|
||||
| RouteOutput
|
||||
| RedirectRouteOutput
|
||||
| WidgetOutput
|
||||
| EntityPageViewRouteOutput
|
||||
| EntityPageNavItemOutput;
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import React, { ComponentType } from 'react';
|
||||
import { App, AppComponentBuilder } from '../app/types';
|
||||
import { Widget } from './types';
|
||||
import BackstagePlugin from '../plugin/Plugin';
|
||||
import DefaultWidgetView from '../../components/DefaultWidgetView';
|
||||
|
||||
type WidgetViewRegistration = {
|
||||
type: 'component';
|
||||
widget: Widget;
|
||||
};
|
||||
type WidgetViewRegistration =
|
||||
| {
|
||||
type: 'component';
|
||||
widget: Widget;
|
||||
}
|
||||
| {
|
||||
type: 'plugin';
|
||||
plugin: BackstagePlugin;
|
||||
};
|
||||
|
||||
export default class WidgetViewBuilder extends AppComponentBuilder {
|
||||
private readonly registrations = new Array<WidgetViewRegistration>();
|
||||
@@ -17,19 +23,41 @@ export default class WidgetViewBuilder extends AppComponentBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
register(plugin: BackstagePlugin): WidgetViewBuilder {
|
||||
this.registrations.push({ type: 'plugin', plugin });
|
||||
return this;
|
||||
}
|
||||
|
||||
build(_app: App): ComponentType<any> {
|
||||
if (this.output) {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
const widgets = this.registrations.map(reg => {
|
||||
const widgets = new Array<Widget>();
|
||||
|
||||
for (const reg of this.registrations) {
|
||||
switch (reg.type) {
|
||||
case 'component':
|
||||
return reg.widget;
|
||||
widgets.push(reg.widget);
|
||||
break;
|
||||
case 'plugin':
|
||||
let added = false;
|
||||
for (const output of reg.plugin.output()) {
|
||||
if (output.type === 'widget') {
|
||||
widgets.push(output.widget);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
throw new Error(
|
||||
`Plugin ${reg.plugin} was registered as widget provider, but did not provide any widgets`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown WidgetViewBuilder registration`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.output = () => <DefaultWidgetView widgets={widgets} />;
|
||||
return this.output;
|
||||
|
||||
Reference in New Issue
Block a user