PluginExtensions: Start using new APIs for datasource config extensions point (#101139)
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { screen, render } from '@testing-library/react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { PluginExtensionTypes, PluginState } from '@grafana/data';
|
||||
import { setAngularLoader, setPluginExtensionsHook } from '@grafana/runtime';
|
||||
import { PluginState } from '@grafana/data';
|
||||
import { setAngularLoader, setPluginComponentsHook } from '@grafana/runtime';
|
||||
import { createComponentWithMeta } from 'app/features/plugins/extensions/usePluginComponents';
|
||||
import { configureStore } from 'app/store/configureStore';
|
||||
|
||||
import { getMockDataSource, getMockDataSourceMeta, getMockDataSourceSettingsState } from '../__mocks__';
|
||||
@@ -58,7 +59,7 @@ describe('<EditDataSource>', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setPluginExtensionsHook(jest.fn().mockReturnValue({ extensions: [] }));
|
||||
setPluginComponentsHook(jest.fn().mockReturnValue({ isLoading: false, components: [] }));
|
||||
});
|
||||
|
||||
describe('On loading errors', () => {
|
||||
@@ -268,17 +269,19 @@ describe('<EditDataSource>', () => {
|
||||
it('should be possible to extend the form with a "component" extension in case the plugin ID is whitelisted', () => {
|
||||
const message = "I'm a UI extension component!";
|
||||
|
||||
setPluginExtensionsHook(
|
||||
setPluginComponentsHook(
|
||||
jest.fn().mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: 'grafana-pdc-app',
|
||||
type: PluginExtensionTypes.component,
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component: () => <div>{message}</div>,
|
||||
},
|
||||
isLoading: false,
|
||||
components: [
|
||||
createComponentWithMeta(
|
||||
{
|
||||
pluginId: 'grafana-pdc-app',
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component: () => <div>{message}</div>,
|
||||
},
|
||||
'1'
|
||||
),
|
||||
],
|
||||
})
|
||||
);
|
||||
@@ -297,17 +300,19 @@ describe('<EditDataSource>', () => {
|
||||
it('should NOT be possible to extend the form with a "component" extension in case the plugin ID is NOT whitelisted', () => {
|
||||
const message = "I'm a UI extension component!";
|
||||
|
||||
setPluginExtensionsHook(
|
||||
setPluginComponentsHook(
|
||||
jest.fn().mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: 'myorg-basic-app',
|
||||
type: PluginExtensionTypes.component,
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component: () => <div>{message}</div>,
|
||||
},
|
||||
isLoading: false,
|
||||
components: [
|
||||
createComponentWithMeta(
|
||||
{
|
||||
pluginId: 'myorg-basic-app',
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component: () => <div>{message}</div>,
|
||||
},
|
||||
'1'
|
||||
),
|
||||
],
|
||||
})
|
||||
);
|
||||
@@ -327,17 +332,19 @@ describe('<EditDataSource>', () => {
|
||||
const message = "I'm a UI extension component!";
|
||||
const component = jest.fn().mockReturnValue(<div>{message}</div>);
|
||||
|
||||
setPluginExtensionsHook(
|
||||
setPluginComponentsHook(
|
||||
jest.fn().mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: 'grafana-pdc-app',
|
||||
type: PluginExtensionTypes.component,
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component,
|
||||
},
|
||||
isLoading: false,
|
||||
components: [
|
||||
createComponentWithMeta(
|
||||
{
|
||||
pluginId: 'grafana-pdc-app',
|
||||
title: 'Example component',
|
||||
description: 'Example description',
|
||||
component,
|
||||
},
|
||||
'1'
|
||||
),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
@@ -9,10 +9,9 @@ import {
|
||||
DataSourceSettings as DataSourceSettingsType,
|
||||
PluginExtensionPoints,
|
||||
PluginExtensionDataSourceConfigContext,
|
||||
DataSourceJsonData,
|
||||
DataSourceUpdatedSuccessfully,
|
||||
} from '@grafana/data';
|
||||
import { getDataSourceSrv, usePluginComponentExtensions } from '@grafana/runtime';
|
||||
import { getDataSourceSrv, usePluginComponents, UsePluginComponentsResult } from '@grafana/runtime';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import PageLoader from 'app/core/components/PageLoader/PageLoader';
|
||||
import { DataSourceSettingsState, useDispatch } from 'app/types';
|
||||
@@ -118,6 +117,7 @@ export function EditDataSourceView({
|
||||
const { plugin, loadError, testingStatus, loading } = dataSourceSettings;
|
||||
const { readOnly, hasWriteRights, hasDeleteRights } = dataSourceRights;
|
||||
const hasDataSource = dataSource.id > 0;
|
||||
const { components, isLoading } = useDataSourceConfigPluginExtensions();
|
||||
|
||||
const dsi = getDataSourceSrv()?.getInstanceSettings(dataSource.uid);
|
||||
|
||||
@@ -137,16 +137,6 @@ export function EditDataSourceView({
|
||||
onTest();
|
||||
};
|
||||
|
||||
const extensionPointId = PluginExtensionPoints.DataSourceConfig;
|
||||
const { extensions } = usePluginComponentExtensions<{
|
||||
context: PluginExtensionDataSourceConfigContext<DataSourceJsonData>;
|
||||
}>({ extensionPointId });
|
||||
|
||||
const allowedExtensions = useMemo(() => {
|
||||
const allowedPluginIds = ['grafana-pdc-app', 'grafana-auth-app'];
|
||||
return extensions.filter((e) => allowedPluginIds.includes(e.pluginId));
|
||||
}, [extensions]);
|
||||
|
||||
if (loadError) {
|
||||
return (
|
||||
<DataSourceLoadError
|
||||
@@ -159,7 +149,7 @@ export function EditDataSourceView({
|
||||
);
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
if (loading || isLoading) {
|
||||
return <PageLoader />;
|
||||
}
|
||||
|
||||
@@ -204,11 +194,9 @@ export function EditDataSourceView({
|
||||
)}
|
||||
|
||||
{/* Extension point */}
|
||||
{allowedExtensions.map((extension) => {
|
||||
const Component = extension.component;
|
||||
|
||||
{components.map((Component) => {
|
||||
return (
|
||||
<div key={extension.id}>
|
||||
<div key={Component.meta.id}>
|
||||
<Component
|
||||
context={{
|
||||
dataSource: cloneDeep(dataSource),
|
||||
@@ -248,3 +236,27 @@ export function EditDataSourceView({
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
type DataSourceConfigPluginExtensionProps = {
|
||||
context: PluginExtensionDataSourceConfigContext;
|
||||
};
|
||||
|
||||
function useDataSourceConfigPluginExtensions(): UsePluginComponentsResult<DataSourceConfigPluginExtensionProps> {
|
||||
const { components, isLoading } = usePluginComponents<DataSourceConfigPluginExtensionProps>({
|
||||
extensionPointId: PluginExtensionPoints.DataSourceConfig,
|
||||
});
|
||||
|
||||
return useMemo(() => {
|
||||
const allowedComponents = components.filter((component) => {
|
||||
switch (component.meta.pluginId) {
|
||||
case 'grafana-pdc-app':
|
||||
case 'grafana-auth-app':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return { components: allowedComponents, isLoading };
|
||||
}, [components, isLoading]);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ export function usePluginComponents<Props extends object = {}>({
|
||||
}, [extensionPointId, limitPerPlugin, pluginContext, registryState, isLoadingAppPlugins]);
|
||||
}
|
||||
|
||||
function createComponentWithMeta<Props extends JSX.IntrinsicAttributes>(
|
||||
// exported so it can be used in tests
|
||||
export function createComponentWithMeta<Props extends JSX.IntrinsicAttributes>(
|
||||
registryItem: AddedComponentRegistryItem<Props>,
|
||||
extensionPointId: string
|
||||
): React.ComponentType<Props> & { meta: PluginExtensionComponentMeta } {
|
||||
|
||||
Reference in New Issue
Block a user