From dc6d0a2bdb0078bf9dd7676a7ecd5ebb31daa8c1 Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Thu, 2 Mar 2023 09:50:01 +0100 Subject: [PATCH] Nav: Handle app plugin installation/uninstallation (#63706) --- public/app/core/reducers/navBarTree.ts | 9 +++- .../InstallControls/InstallControlsButton.tsx | 18 ++++++- .../admin/components/PluginActions.tsx | 54 +++++++++++++------ 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/public/app/core/reducers/navBarTree.ts b/public/app/core/reducers/navBarTree.ts index 49951bd181b..d5fba3cd666 100644 --- a/public/app/core/reducers/navBarTree.ts +++ b/public/app/core/reducers/navBarTree.ts @@ -63,8 +63,15 @@ const navTreeSlice = createSlice({ } } }, + removePluginFromNavTree: (state, action: PayloadAction<{ pluginID: string }>) => { + const navID = 'plugin-page-' + action.payload.pluginID; + const pluginItemIndex = state.findIndex((navItem) => navItem.id === navID); + if (pluginItemIndex > -1) { + state.splice(pluginItemIndex, 1); + } + }, }, }); -export const { setStarred, updateDashboardName } = navTreeSlice.actions; +export const { setStarred, removePluginFromNavTree, updateDashboardName } = navTreeSlice.actions; export const navTreeReducer = navTreeSlice.reducer; diff --git a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx index cf7ad12181f..c79e754c0a9 100644 --- a/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx +++ b/public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx @@ -6,6 +6,8 @@ import { locationService } from '@grafana/runtime'; import { Button, HorizontalGroup, ConfirmModal } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; +import { removePluginFromNavTree } from 'app/core/reducers/navBarTree'; +import { useDispatch } from 'app/types'; import { useInstallStatus, useUninstallStatus, useInstall, useUninstall } from '../../state/hooks'; import { trackPluginInstalled, trackPluginUninstalled } from '../../tracking'; @@ -15,9 +17,16 @@ type InstallControlsButtonProps = { plugin: CatalogPlugin; pluginStatus: PluginStatus; latestCompatibleVersion?: Version; + setNeedReload: (needReload: boolean) => void; }; -export function InstallControlsButton({ plugin, pluginStatus, latestCompatibleVersion }: InstallControlsButtonProps) { +export function InstallControlsButton({ + plugin, + pluginStatus, + latestCompatibleVersion, + setNeedReload, +}: InstallControlsButtonProps) { + const dispatch = useDispatch(); const [queryParams] = useQueryParams(); const location = useLocation(); const { isInstalling, error: errorInstalling } = useInstallStatus(); @@ -39,6 +48,9 @@ export function InstallControlsButton({ plugin, pluginStatus, latestCompatibleVe await install(plugin.id, latestCompatibleVersion?.version); if (!errorInstalling) { appEvents.emit(AppEvents.alertSuccess, [`Installed ${plugin.name}`]); + if (plugin.type === 'app') { + setNeedReload(true); + } } }; @@ -54,6 +66,10 @@ export function InstallControlsButton({ plugin, pluginStatus, latestCompatibleVe locationService.replace(`${location.pathname}?page=${PluginTabIds.OVERVIEW}`); } appEvents.emit(AppEvents.alertSuccess, [`Uninstalled ${plugin.name}`]); + if (plugin.type === 'app') { + dispatch(removePluginFromNavTree({ pluginID: plugin.id })); + setNeedReload(false); + } } }; diff --git a/public/app/features/plugins/admin/components/PluginActions.tsx b/public/app/features/plugins/admin/components/PluginActions.tsx index 6819da2b6e0..055050ef066 100644 --- a/public/app/features/plugins/admin/components/PluginActions.tsx +++ b/public/app/features/plugins/admin/components/PluginActions.tsx @@ -1,6 +1,9 @@ -import React from 'react'; +import { css } from '@emotion/css'; +import React, { useState } from 'react'; +import { GrafanaTheme2 } from '@grafana/data'; import { config } from '@grafana/runtime'; +import { HorizontalGroup, Icon, useStyles2, VerticalGroup } from '@grafana/ui'; import { GetStartedWithPlugin } from '../components/GetStartedWithPlugin'; import { InstallControlsButton } from '../components/InstallControls'; @@ -14,8 +17,10 @@ interface Props { } export const PluginActions = ({ plugin }: Props) => { + const styles = useStyles2(getStyles); const isRemotePluginsAvailable = useIsRemotePluginsAvailable(); const latestCompatibleVersion = getLatestCompatibleVersion(plugin?.details?.versions); + const [needReload, setNeedReload] = useState(false); if (!plugin) { return null; @@ -32,21 +37,38 @@ export const PluginActions = ({ plugin }: Props) => { plugin.isCore || plugin.isDisabled || !isInstallControlsEnabled() || hasInstallWarning; return ( - <> - {!isInstallControlsDisabled && ( - <> - {isExternallyManaged ? ( - - ) : ( - - )} - + + + {!isInstallControlsDisabled && ( + <> + {isExternallyManaged ? ( + + ) : ( + + )} + + )} + + + {needReload && ( + + + Refresh the page to see the changes + )} - - + ); }; + +const getStyles = (theme: GrafanaTheme2) => { + return { + message: css` + color: ${theme.colors.text.secondary}; + `, + }; +};