diff --git a/public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx b/public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx index de1d244ca2b..3078c73d0b1 100644 --- a/public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx +++ b/public/app/features/plugins/admin/components/Badges/PluginUpdateAvailableBadge.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { css } from '@emotion/css'; -import { GrafanaTheme2 } from '@grafana/data'; +import { GrafanaTheme2, PluginType } from '@grafana/data'; import { Tooltip, useStyles2 } from '@grafana/ui'; import { CatalogPlugin } from '../../types'; @@ -11,7 +11,7 @@ type Props = { export function PluginUpdateAvailableBadge({ plugin }: Props): React.ReactElement | null { const styles = useStyles2(getStyles); - if (plugin.hasUpdate && !plugin.isCore) { + if (plugin.hasUpdate && !plugin.isCore && plugin.type !== PluginType.renderer) { return (

Update available!

diff --git a/public/app/features/plugins/admin/components/InstallControls/index.tsx b/public/app/features/plugins/admin/components/InstallControls/index.tsx index 16110ddce1e..6cc39a31035 100644 --- a/public/app/features/plugins/admin/components/InstallControls/index.tsx +++ b/public/app/features/plugins/admin/components/InstallControls/index.tsx @@ -4,12 +4,12 @@ import { satisfies } from 'semver'; import { config } from '@grafana/runtime'; import { HorizontalGroup, Icon, LinkButton, useStyles2 } from '@grafana/ui'; -import { GrafanaTheme2 } from '@grafana/data'; +import { GrafanaTheme2, PluginType } from '@grafana/data'; import { ExternallyManagedButton } from './ExternallyManagedButton'; import { InstallControlsButton } from './InstallControlsButton'; import { CatalogPlugin, PluginStatus } from '../../types'; -import { isGrafanaAdmin, getExternalManageLink } from '../../helpers'; +import { getExternalManageLink, isGrafanaAdmin } from '../../helpers'; import { useIsRemotePluginsAvailable } from '../../state/hooks'; interface Props { @@ -38,6 +38,10 @@ export const InstallControls = ({ plugin }: Props) => { return null; } + if (plugin.type === PluginType.renderer) { + return
Renderer plugins cannot be managed by the Plugin Catalog.
; + } + if (plugin.isEnterprise && !config.licenseInfo?.hasValidLicense) { return ( diff --git a/public/app/features/plugins/admin/hooks/usePlugins.tsx b/public/app/features/plugins/admin/hooks/usePlugins.tsx deleted file mode 100644 index 475bf1e4330..00000000000 --- a/public/app/features/plugins/admin/hooks/usePlugins.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useMemo } from 'react'; -import { useAsync } from 'react-use'; -import { CatalogPlugin, CatalogPluginsState } from '../types'; -import { api } from '../api'; -import { mapLocalToCatalog, mapRemoteToCatalog, mapToCatalogPlugin } from '../helpers'; - -export function usePlugins(): CatalogPluginsState { - const { loading, value, error } = useAsync(async () => { - const remote = await api.getRemotePlugins(); - const installed = await api.getInstalledPlugins(); - return { remote, installed }; - }, []); - - const plugins = useMemo(() => { - const installed = value?.installed || []; - const remote = value?.remote || []; - const unique: Record = {}; - - for (const plugin of installed) { - unique[plugin.id] = mapLocalToCatalog(plugin); - } - - for (const plugin of remote) { - if (plugin.typeCode === 'renderer') { - continue; - } - - if (!Boolean(plugin.versionSignatureType)) { - continue; - } - - if (unique[plugin.slug]) { - unique[plugin.slug] = mapToCatalogPlugin( - installed.find((installedPlugin) => installedPlugin.id === plugin.slug), - plugin - ); - } else { - unique[plugin.slug] = mapRemoteToCatalog(plugin); - } - } - return Object.values(unique); - }, [value?.installed, value?.remote]); - - return { - loading, - error, - plugins, - }; -} diff --git a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx index fe2f6fc1914..61e222bbea2 100644 --- a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx +++ b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx @@ -11,7 +11,7 @@ import { CatalogPlugin, PluginTabIds, RequestStatus, ReducerState } from '../typ import * as api from '../api'; import { fetchRemotePlugins } from '../state/actions'; import { mockPluginApis, getCatalogPluginMock, getPluginsStateMock } from '../__mocks__'; -import { PluginErrorCode, PluginSignatureStatus } from '@grafana/data'; +import { PluginErrorCode, PluginSignatureStatus, PluginType } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; jest.mock('@grafana/runtime', () => { @@ -255,6 +255,13 @@ describe('Plugin details page', () => { await waitFor(() => expect(queryByRole('button', { name: /(un)?install/i })).not.toBeInTheDocument()); }); + it('should not display install / uninstall buttons for renderer plugins', async () => { + const { queryByRole } = renderPluginDetails({ id, type: PluginType.renderer }); + + await waitFor(() => expect(queryByRole('button', { name: /update/i })).not.toBeInTheDocument()); + await waitFor(() => expect(queryByRole('button', { name: /(un)?install/i })).not.toBeInTheDocument()); + }); + it('should display install link with `config.pluginAdminExternalManageEnabled` set to true', async () => { config.pluginAdminExternalManageEnabled = true;