From 7773c658bb3280f0432fc9742109f8eb324c83a3 Mon Sep 17 00:00:00 2001 From: Marcus Andersson Date: Tue, 25 Feb 2025 09:17:17 +0100 Subject: [PATCH] PluginExtensions: Start using new APIs for datasource config extensions point (#101139) --- .../components/EditDataSource.test.tsx | 73 ++++++++++--------- .../datasources/components/EditDataSource.tsx | 46 +++++++----- .../extensions/usePluginComponents.tsx | 3 +- 3 files changed, 71 insertions(+), 51 deletions(-) diff --git a/public/app/features/datasources/components/EditDataSource.test.tsx b/public/app/features/datasources/components/EditDataSource.test.tsx index 378695c0506..be1736f77ee 100644 --- a/public/app/features/datasources/components/EditDataSource.test.tsx +++ b/public/app/features/datasources/components/EditDataSource.test.tsx @@ -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('', () => { }); beforeEach(() => { - setPluginExtensionsHook(jest.fn().mockReturnValue({ extensions: [] })); + setPluginComponentsHook(jest.fn().mockReturnValue({ isLoading: false, components: [] })); }); describe('On loading errors', () => { @@ -268,17 +269,19 @@ describe('', () => { 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: () =>
{message}
, - }, + isLoading: false, + components: [ + createComponentWithMeta( + { + pluginId: 'grafana-pdc-app', + title: 'Example component', + description: 'Example description', + component: () =>
{message}
, + }, + '1' + ), ], }) ); @@ -297,17 +300,19 @@ describe('', () => { 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: () =>
{message}
, - }, + isLoading: false, + components: [ + createComponentWithMeta( + { + pluginId: 'myorg-basic-app', + title: 'Example component', + description: 'Example description', + component: () =>
{message}
, + }, + '1' + ), ], }) ); @@ -327,17 +332,19 @@ describe('', () => { const message = "I'm a UI extension component!"; const component = jest.fn().mockReturnValue(
{message}
); - 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' + ), ], }) ); diff --git a/public/app/features/datasources/components/EditDataSource.tsx b/public/app/features/datasources/components/EditDataSource.tsx index e948bad2013..7fe90eba063 100644 --- a/public/app/features/datasources/components/EditDataSource.tsx +++ b/public/app/features/datasources/components/EditDataSource.tsx @@ -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; - }>({ extensionPointId }); - - const allowedExtensions = useMemo(() => { - const allowedPluginIds = ['grafana-pdc-app', 'grafana-auth-app']; - return extensions.filter((e) => allowedPluginIds.includes(e.pluginId)); - }, [extensions]); - if (loadError) { return ( ; } @@ -204,11 +194,9 @@ export function EditDataSourceView({ )} {/* Extension point */} - {allowedExtensions.map((extension) => { - const Component = extension.component; - + {components.map((Component) => { return ( -
+
); } + +type DataSourceConfigPluginExtensionProps = { + context: PluginExtensionDataSourceConfigContext; +}; + +function useDataSourceConfigPluginExtensions(): UsePluginComponentsResult { + const { components, isLoading } = usePluginComponents({ + 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]); +} diff --git a/public/app/features/plugins/extensions/usePluginComponents.tsx b/public/app/features/plugins/extensions/usePluginComponents.tsx index d5259a85c41..c3e406d5d23 100644 --- a/public/app/features/plugins/extensions/usePluginComponents.tsx +++ b/public/app/features/plugins/extensions/usePluginComponents.tsx @@ -80,7 +80,8 @@ export function usePluginComponents({ }, [extensionPointId, limitPerPlugin, pluginContext, registryState, isLoadingAppPlugins]); } -function createComponentWithMeta( +// exported so it can be used in tests +export function createComponentWithMeta( registryItem: AddedComponentRegistryItem, extensionPointId: string ): React.ComponentType & { meta: PluginExtensionComponentMeta } {