Plugins: Fix version tab breaking for non semantic version (#101225)
This commit is contained in:
@@ -177,6 +177,46 @@ describe('VersionInstallButton', () => {
|
||||
);
|
||||
expect(screen.getByText('Downgrade')).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('should show the installation button if invalid semver version is provided', () => {
|
||||
const version: Version = {
|
||||
version: '1.0.a',
|
||||
createdAt: '',
|
||||
isCompatible: false,
|
||||
grafanaDependency: null,
|
||||
};
|
||||
const installedVersion = '1.0.1';
|
||||
renderWithStore(
|
||||
<VersionInstallButton
|
||||
installedVersion={installedVersion}
|
||||
pluginId={'test'}
|
||||
version={version}
|
||||
disabled={false}
|
||||
onConfirmInstallation={() => {}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Install')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show the installation button if invalid semver installed version is provided', () => {
|
||||
const version: Version = {
|
||||
version: '1.0.0',
|
||||
createdAt: '',
|
||||
isCompatible: false,
|
||||
grafanaDependency: null,
|
||||
};
|
||||
const installedVersion = '1.0.a';
|
||||
renderWithStore(
|
||||
<VersionInstallButton
|
||||
installedVersion={installedVersion}
|
||||
pluginId={'test'}
|
||||
version={version}
|
||||
disabled={false}
|
||||
onConfirmInstallation={() => {}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Install')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
function renderWithStore(component: JSX.Element) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { gt } from 'semver';
|
||||
import { gt, valid } from 'semver';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
@@ -14,6 +14,12 @@ import { Version } from '../types';
|
||||
const PLUGINS_VERSION_PAGE_UPGRADE_INTERACTION_EVENT_NAME = 'plugins_upgrade_clicked';
|
||||
const PLUGINS_VERSION_PAGE_CHANGE_INTERACTION_EVENT_NAME = 'plugins_downgrade_clicked';
|
||||
|
||||
enum InstallState {
|
||||
INSTALL = 'Install',
|
||||
UPGRADE = 'Upgrade',
|
||||
DOWNGRADE = 'Downgrade',
|
||||
}
|
||||
|
||||
interface Props {
|
||||
pluginId: string;
|
||||
version: Version;
|
||||
@@ -38,7 +44,7 @@ export const VersionInstallButton = ({
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const isDowngrade = installedVersion && gt(installedVersion, version.version);
|
||||
const installState = getInstallState(installedVersion, version.version);
|
||||
|
||||
useEffect(() => {
|
||||
if (installedVersion === version.version) {
|
||||
@@ -61,7 +67,7 @@ export const VersionInstallButton = ({
|
||||
schema_version: '1.0.0',
|
||||
};
|
||||
|
||||
if (!installedVersion || gt(version.version, installedVersion)) {
|
||||
if (installState === InstallState.UPGRADE) {
|
||||
reportInteraction(PLUGINS_VERSION_PAGE_UPGRADE_INTERACTION_EVENT_NAME, trackProps);
|
||||
} else {
|
||||
reportInteraction(PLUGINS_VERSION_PAGE_CHANGE_INTERACTION_EVENT_NAME, {
|
||||
@@ -76,7 +82,7 @@ export const VersionInstallButton = ({
|
||||
};
|
||||
|
||||
const onInstallClick = () => {
|
||||
if (isDowngrade) {
|
||||
if (installState === InstallState.DOWNGRADE) {
|
||||
setIsModalOpen(true);
|
||||
} else {
|
||||
performInstallation();
|
||||
@@ -91,24 +97,9 @@ export const VersionInstallButton = ({
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
let label = 'Downgrade';
|
||||
let hidden = false;
|
||||
const isPreinstalled = isPreinstalledPlugin(pluginId);
|
||||
|
||||
if (!installedVersion) {
|
||||
label = 'Install';
|
||||
} else if (gt(version.version, installedVersion)) {
|
||||
label = 'Upgrade';
|
||||
if (isPreinstalled.withVersion) {
|
||||
// Hide button if the plugin is preinstalled with a specific version
|
||||
hidden = true;
|
||||
}
|
||||
} else {
|
||||
if (isPreinstalled.found && Boolean(config.featureToggles.preinstallAutoUpdate)) {
|
||||
// Hide the downgrade button if the plugin is preinstalled since it will be auto-updated
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
const hidden = getButtonHiddenState(installState, isPreinstalled);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -124,7 +115,7 @@ export const VersionInstallButton = ({
|
||||
tooltip={tooltip}
|
||||
tooltipPlacement="bottom-start"
|
||||
>
|
||||
{label} {isInstalling ? <Spinner className={styles.spinner} inline size="sm" /> : getIcon(label)}
|
||||
{installState} {isInstalling ? <Spinner className={styles.spinner} inline size="sm" /> : getIcon(installState)}
|
||||
</Button>
|
||||
<ConfirmModal
|
||||
isOpen={isModalOpen}
|
||||
@@ -140,16 +131,38 @@ export const VersionInstallButton = ({
|
||||
);
|
||||
};
|
||||
|
||||
function getIcon(label: string) {
|
||||
if (label === 'Downgrade') {
|
||||
function getIcon(installState: InstallState) {
|
||||
if (installState === InstallState.DOWNGRADE) {
|
||||
return <Icon name="arrow-down" />;
|
||||
}
|
||||
if (label === 'Upgrade') {
|
||||
if (installState === InstallState.UPGRADE) {
|
||||
return <Icon name="arrow-up" />;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getInstallState(installedVersion?: string, version?: string): InstallState {
|
||||
if (!installedVersion || !version || !valid(installedVersion) || !valid(version)) {
|
||||
return InstallState.INSTALL;
|
||||
}
|
||||
return gt(installedVersion, version) ? InstallState.DOWNGRADE : InstallState.UPGRADE;
|
||||
}
|
||||
|
||||
function getButtonHiddenState(installState: InstallState, isPreinstalled: { found: boolean; withVersion: boolean }) {
|
||||
// Default state for initial install
|
||||
if (installState === InstallState.INSTALL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle downgrade case
|
||||
if (installState === InstallState.DOWNGRADE) {
|
||||
return isPreinstalled.found && Boolean(config.featureToggles.preinstallAutoUpdate);
|
||||
}
|
||||
|
||||
// Handle upgrade case
|
||||
return isPreinstalled.withVersion;
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
spinner: css({
|
||||
marginLeft: theme.spacing(1),
|
||||
|
||||
Reference in New Issue
Block a user