mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins Catalog: show a confirmation modal when uninstalling a plugin (#39244)
* feat(Plugins/Admin): show a confirmation modal when uninstalling a plugin * refactor(Plugins/Admin): use a helper function for showing/hiding the modal * test(Plugins/Admin): test if the modal disappears after an uninstall
This commit is contained in:
parent
35f1d0facb
commit
02f9564607
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useMountedState } from 'react-use';
|
||||
import { AppEvents, PluginType } from '@grafana/data';
|
||||
import { Button, HorizontalGroup, useStyles2 } from '@grafana/ui';
|
||||
import { Button, HorizontalGroup, ConfirmModal, useStyles2 } from '@grafana/ui';
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
import { CatalogPlugin, PluginStatus } from '../../types';
|
||||
@ -18,6 +18,9 @@ export function InstallControlsButton({ plugin, pluginStatus }: InstallControlsB
|
||||
const { isUninstalling, error: errorUninstalling } = useUninstallStatus();
|
||||
const install = useInstall();
|
||||
const uninstall = useUninstall();
|
||||
const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false);
|
||||
const showConfirmModal = () => setIsConfirmModalVisible(true);
|
||||
const hideConfirmModal = () => setIsConfirmModalVisible(false);
|
||||
const [hasInstalledPanel, setHasInstalledPanel] = useState(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
const uninstallBtnText = isUninstalling ? 'Uninstalling' : 'Uninstall';
|
||||
@ -34,6 +37,7 @@ export function InstallControlsButton({ plugin, pluginStatus }: InstallControlsB
|
||||
};
|
||||
|
||||
const onUninstall = async () => {
|
||||
hideConfirmModal();
|
||||
await uninstall(plugin.id);
|
||||
if (!errorUninstalling) {
|
||||
appEvents.emit(AppEvents.alertSuccess, [`Uninstalled ${plugin.name}`]);
|
||||
@ -49,14 +53,25 @@ export function InstallControlsButton({ plugin, pluginStatus }: InstallControlsB
|
||||
|
||||
if (pluginStatus === PluginStatus.UNINSTALL) {
|
||||
return (
|
||||
<HorizontalGroup height="auto">
|
||||
<Button variant="destructive" disabled={isUninstalling} onClick={onUninstall}>
|
||||
{uninstallBtnText}
|
||||
</Button>
|
||||
{hasInstalledPanel && (
|
||||
<div className={styles.message}>Please refresh your browser window before using this plugin.</div>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
<>
|
||||
<ConfirmModal
|
||||
isOpen={isConfirmModalVisible}
|
||||
title={`Uninstall ${plugin.name}`}
|
||||
body="Are you sure you want to uninstall this plugin?"
|
||||
confirmText="Confirm"
|
||||
icon="exclamation-triangle"
|
||||
onConfirm={onUninstall}
|
||||
onDismiss={hideConfirmModal}
|
||||
/>
|
||||
<HorizontalGroup height="auto">
|
||||
<Button variant="destructive" disabled={isUninstalling} onClick={showConfirmModal}>
|
||||
{uninstallBtnText}
|
||||
</Button>
|
||||
{hasInstalledPanel && (
|
||||
<div className={styles.message}>Please refresh your browser window before using this plugin.</div>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { configureStore } from 'app/store/configureStore';
|
||||
import PluginDetailsPage from './PluginDetails';
|
||||
import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps';
|
||||
import { CatalogPlugin } from '../types';
|
||||
import * as api from '../api';
|
||||
import { mockPluginApis, getCatalogPluginMock, getPluginsStateMock } from '../__mocks__';
|
||||
|
||||
// Mock the config to enable the plugin catalog
|
||||
@ -46,6 +47,8 @@ describe('Plugin details page', () => {
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
config.pluginAdminExternalManageEnabled = false;
|
||||
config.licenseInfo.hasValidLicense = false;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@ -208,4 +211,38 @@ describe('Plugin details page', () => {
|
||||
|
||||
expect(queryByText('Grafana >=8.0.0')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show a confirm modal when trying to uninstall a plugin', async () => {
|
||||
// @ts-ignore
|
||||
api.uninstallPlugin = jest.fn();
|
||||
|
||||
const { queryByText, queryByRole, getByRole } = renderPluginDetails({
|
||||
id,
|
||||
name: 'Akumuli',
|
||||
isInstalled: true,
|
||||
details: {
|
||||
pluginDependencies: [],
|
||||
grafanaDependency: '>=8.0.0',
|
||||
links: [],
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for the install controls to be loaded
|
||||
await waitFor(() => expect(queryByRole('button', { name: /install/i })).toBeInTheDocument());
|
||||
|
||||
// Open the confirmation modal
|
||||
userEvent.click(getByRole('button', { name: /uninstall/i }));
|
||||
|
||||
expect(queryByText('Uninstall Akumuli')).toBeInTheDocument();
|
||||
expect(queryByText('Are you sure you want to uninstall this plugin?')).toBeInTheDocument();
|
||||
expect(api.uninstallPlugin).toHaveBeenCalledTimes(0);
|
||||
|
||||
// Confirm the uninstall
|
||||
userEvent.click(getByRole('button', { name: /confirm/i }));
|
||||
expect(api.uninstallPlugin).toHaveBeenCalledTimes(1);
|
||||
expect(api.uninstallPlugin).toHaveBeenCalledWith(id);
|
||||
|
||||
// Check if the modal disappeared
|
||||
expect(queryByText('Uninstall Akumuli')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user