Catalog: Show install error with incompatible version (#65059)

This commit is contained in:
Andres Martinez Gotor
2023-04-19 10:22:24 +02:00
committed by GitHub
parent bc5881a051
commit 98778289cb
8 changed files with 54 additions and 13 deletions

View File

@@ -103,7 +103,10 @@ export async function getLocalPlugins(): Promise<LocalPlugin[]> {
export async function installPlugin(id: string) {
// This will install the latest compatible version based on the logic
// on the backend.
return await getBackendSrv().post(`${API_ROOT}/${id}/install`);
return await getBackendSrv().post(`${API_ROOT}/${id}/install`, undefined, {
// Error is displayed in the page
showErrorAlert: false,
});
}
export async function uninstallPlugin(id: string) {

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { AppEvents } from '@grafana/data';
@@ -9,7 +9,7 @@ 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 { useInstallStatus, useUninstallStatus, useInstall, useUninstall, useUnsetInstall } from '../../state/hooks';
import { trackPluginInstalled, trackPluginUninstalled } from '../../tracking';
import { CatalogPlugin, PluginStatus, PluginTabIds, Version } from '../../types';
@@ -33,6 +33,7 @@ export function InstallControlsButton({
const { isUninstalling, error: errorUninstalling } = useUninstallStatus();
const install = useInstall();
const uninstall = useUninstall();
const unsetInstall = useUnsetInstall();
const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false);
const showConfirmModal = () => setIsConfirmModalVisible(true);
const hideConfirmModal = () => setIsConfirmModalVisible(false);
@@ -43,10 +44,18 @@ export function InstallControlsButton({
path: location.pathname,
};
useEffect(() => {
return () => {
// Remove possible installation errors
unsetInstall();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onInstall = async () => {
trackPluginInstalled(trackingProps);
await install(plugin.id, latestCompatibleVersion?.version);
if (!errorInstalling) {
const result = await install(plugin.id, latestCompatibleVersion?.version);
if (!errorInstalling && !('error' in result)) {
appEvents.emit(AppEvents.alertSuccess, [`Installed ${plugin.name}`]);
if (plugin.type === 'app') {
setNeedReload(true);
@@ -115,7 +124,7 @@ export function InstallControlsButton({
}
return (
<Button disabled={isInstalling} onClick={onInstall}>
<Button disabled={isInstalling || errorInstalling} onClick={onInstall}>
{isInstalling ? 'Installing' : 'Install'}
</Button>
);

View File

@@ -2,11 +2,11 @@ import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
import { Alert, useStyles2 } from '@grafana/ui';
import { InstallControlsWarning } from '../components/InstallControls';
import { getLatestCompatibleVersion, hasInstallControlWarning } from '../helpers';
import { useIsRemotePluginsAvailable } from '../state/hooks';
import { useInstallStatus, useIsRemotePluginsAvailable } from '../state/hooks';
import { CatalogPlugin, PluginStatus } from '../types';
interface Props {
@@ -16,6 +16,7 @@ interface Props {
export const PluginSubtitle = ({ plugin }: Props) => {
const isRemotePluginsAvailable = useIsRemotePluginsAvailable();
const styles = useStyles2(getStyles);
const { error: errorInstalling } = useInstallStatus();
if (!plugin) {
return null;
}
@@ -28,6 +29,11 @@ export const PluginSubtitle = ({ plugin }: Props) => {
return (
<div className={styles.subtitle}>
{errorInstalling && (
<Alert title={'message' in errorInstalling ? errorInstalling.message : ''}>
{typeof errorInstalling === 'string' ? errorInstalling : errorInstalling.error}
</Alert>
)}
{plugin?.description && <div>{plugin?.description}</div>}
{plugin?.details?.links && plugin.details.links.length > 0 && (
<span>

View File

@@ -87,12 +87,17 @@ export const install = createAsyncThunk(
return { id, changes } as Update<CatalogPlugin>;
} catch (e) {
console.error(e);
if (isFetchError(e)) {
return thunkApi.rejectWithValue(e.data);
}
return thunkApi.rejectWithValue('Unknown error.');
}
}
);
export const unsetInstall = createAsyncThunk(`${STATE_PREFIX}/install`, async () => ({}));
export const uninstall = createAsyncThunk(`${STATE_PREFIX}/uninstall`, async (id: string, thunkApi) => {
try {
await uninstallPlugin(id);

View File

@@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'app/types';
import { sortPlugins, Sorters } from '../helpers';
import { CatalogPlugin, PluginListDisplayMode } from '../types';
import { fetchAll, fetchDetails, fetchRemotePlugins, install, uninstall, fetchAllLocal } from './actions';
import { fetchAll, fetchDetails, fetchRemotePlugins, install, uninstall, fetchAllLocal, unsetInstall } from './actions';
import { setDisplayMode } from './reducer';
import {
find,
@@ -74,6 +74,12 @@ export const useInstall = () => {
return (id: string, version?: string, isUpdating?: boolean) => dispatch(install({ id, version, isUpdating }));
};
export const useUnsetInstall = () => {
const dispatch = useDispatch();
return () => dispatch(unsetInstall());
};
export const useUninstall = () => {
const dispatch = useDispatch();