diff --git a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.test.tsx b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.test.tsx
index 74ee6e929e5..be65618a497 100644
--- a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.test.tsx
+++ b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.test.tsx
@@ -69,4 +69,24 @@ describe('InstallControlsButton', () => {
});
}
);
+
+ it("should allow to uninstall a plugin even if it's unpublished", () => {
+ render(
+
+
+
+ );
+ const el = screen.getByRole('button');
+ expect(el).toHaveTextContent(/uninstall/i);
+ expect(el).toBeVisible();
+ });
+
+ it('should not render install or upgrade buttons if the plugin is unpublished', () => {
+ render(
+
+
+
+ );
+ expect(screen.queryByRole('button')).not.toBeInTheDocument();
+ });
});
diff --git a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx
index 86778817a8d..f7ef5e6ede7 100644
--- a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx
+++ b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx
@@ -17,6 +17,7 @@ type InstallControlsButtonProps = {
plugin: CatalogPlugin;
pluginStatus: PluginStatus;
latestCompatibleVersion?: Version;
+ hasInstallWarning?: boolean;
setNeedReload?: (needReload: boolean) => void;
};
@@ -24,6 +25,7 @@ export function InstallControlsButton({
plugin,
pluginStatus,
latestCompatibleVersion,
+ hasInstallWarning,
setNeedReload,
}: InstallControlsButtonProps) {
const dispatch = useDispatch();
@@ -110,6 +112,11 @@ export function InstallControlsButton({
);
}
+ if (!plugin.isPublished || hasInstallWarning) {
+ // Cannot be updated or installed
+ return null;
+ }
+
if (pluginStatus === PluginStatus.UPDATE) {
return (
diff --git a/public/app/features/plugins/admin/components/PluginActions.tsx b/public/app/features/plugins/admin/components/PluginActions.tsx
index ae46d10a774..4ee30e3f0b6 100644
--- a/public/app/features/plugins/admin/components/PluginActions.tsx
+++ b/public/app/features/plugins/admin/components/PluginActions.tsx
@@ -33,15 +33,14 @@ export const PluginActions = ({ plugin }: Props) => {
? PluginStatus.UPDATE
: PluginStatus.UNINSTALL
: PluginStatus.INSTALL;
- const isInstallControlsDisabled =
- plugin.isCore || plugin.isDisabled || !isInstallControlsEnabled() || hasInstallWarning;
+ const isInstallControlsDisabled = plugin.isCore || plugin.isDisabled || !isInstallControlsEnabled();
return (
{!isInstallControlsDisabled && (
<>
- {isExternallyManaged ? (
+ {isExternallyManaged && !hasInstallWarning ? (
{
latestCompatibleVersion={latestCompatibleVersion}
pluginStatus={pluginStatus}
setNeedReload={setNeedReload}
+ hasInstallWarning={hasInstallWarning}
/>
)}
>
diff --git a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx
index ba4a8774fd5..bd004063525 100644
--- a/public/app/features/plugins/admin/pages/PluginDetails.test.tsx
+++ b/public/app/features/plugins/admin/pages/PluginDetails.test.tsx
@@ -324,12 +324,13 @@ describe('Plugin details page', () => {
expect(await queryByRole('button', { name: /install/i })).toBeInTheDocument();
});
- it('should not display install button for enterprise plugins if license is invalid', async () => {
+ it('should not display install button for enterprise plugins if license is invalid (but allow uninstall)', async () => {
config.licenseInfo.enabledFeatures = {};
const { queryByRole, queryByText } = renderPluginDetails({ id, isInstalled: true, isEnterprise: true });
- expect(await queryByRole('button', { name: /install/i })).not.toBeInTheDocument();
+ expect(await queryByRole('button', { name: /Install/ })).not.toBeInTheDocument();
+ expect(await queryByRole('button', { name: /Uninstall/ })).toBeInTheDocument();
expect(queryByText(/no valid Grafana Enterprise license detected/i)).toBeInTheDocument();
expect(queryByRole('link', { name: /learn more/i })).toBeInTheDocument();
});