From ad888813c636eb7b691271a4465c9d90f5e19f06 Mon Sep 17 00:00:00 2001 From: Marcus Andersson Date: Tue, 2 Nov 2021 13:41:08 +0100 Subject: [PATCH] PluginsCatalog: Fix so we display the correct badges when a plugin is disabled. (#41159) --- .../components/PluginDetailsDisabledError.tsx | 6 +-- .../PluginDetailsHeaderSignature.tsx | 27 ++++++++++-- .../components/PluginDetailsSignature.tsx | 20 ++++++++- public/app/features/plugins/admin/helpers.ts | 41 +++++++++++++++---- .../plugins/admin/pages/PluginDetails.tsx | 2 +- 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx b/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx index 88eadc6a23d..12b6b6cf043 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { ReactElement } from 'react'; import { PluginErrorCode } from '@grafana/data'; import { Alert } from '@grafana/ui'; import { CatalogPlugin } from '../types'; @@ -9,7 +9,7 @@ type Props = { plugin: CatalogPlugin; }; -export function PluginDetailsDisabledError({ className, plugin }: Props): React.ReactElement | null { +export function PluginDetailsDisabledError({ className, plugin }: Props): ReactElement | null { if (!plugin.isDisabled) { return null; } @@ -35,7 +35,7 @@ export function PluginDetailsDisabledError({ className, plugin }: Props): React. ); } -function renderDescriptionFromError(error?: PluginErrorCode): React.ReactElement { +function renderDescriptionFromError(error?: PluginErrorCode): ReactElement { switch (error) { case PluginErrorCode.modifiedSignature: return ( diff --git a/public/app/features/plugins/admin/components/PluginDetailsHeaderSignature.tsx b/public/app/features/plugins/admin/components/PluginDetailsHeaderSignature.tsx index 93fe8d5d114..5c73d09d048 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsHeaderSignature.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsHeaderSignature.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { PluginSignatureStatus } from '@grafana/data'; -import { PluginSignatureBadge } from '@grafana/ui'; +import { css } from '@emotion/css'; +import { GrafanaTheme2, PluginSignatureStatus } from '@grafana/data'; +import { PluginSignatureBadge, useStyles2 } from '@grafana/ui'; import { PluginSignatureDetailsBadge } from './PluginSignatureDetailsBadge'; import { CatalogPlugin } from '../types'; @@ -10,11 +11,17 @@ type Props = { // Designed to show plugin signature information in the header on the plugin's details page export function PluginDetailsHeaderSignature({ plugin }: Props): React.ReactElement { + const styles = useStyles2(getStyles); const isSignatureValid = plugin.signature === PluginSignatureStatus.valid; return ( -
- +
+ @@ -24,3 +31,15 @@ export function PluginDetailsHeaderSignature({ plugin }: Props): React.ReactElem
); } + +export const getStyles = (theme: GrafanaTheme2) => { + return { + container: css` + display: flex; + `, + link: css` + display: inline-flex; + align-items: center; + `, + }; +}; diff --git a/public/app/features/plugins/admin/components/PluginDetailsSignature.tsx b/public/app/features/plugins/admin/components/PluginDetailsSignature.tsx index 99ce7f2c420..210d71b73b3 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsSignature.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsSignature.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { selectors } from '@grafana/e2e-selectors'; -import { PluginSignatureStatus } from '@grafana/data'; +import { PluginErrorCode, PluginSignatureStatus } from '@grafana/data'; import { Alert } from '@grafana/ui'; import { CatalogPlugin } from '../types'; @@ -13,9 +13,10 @@ type Props = { export function PluginDetailsSignature({ className, plugin }: Props): React.ReactElement | null { const isSignatureValid = plugin.signature === PluginSignatureStatus.valid; const isCore = plugin.signature === PluginSignatureStatus.internal; + const isDisabled = plugin.isDisabled && isDisabledDueTooSignatureError(plugin.error); // The basic information is already available in the header - if (isSignatureValid || isCore) { + if (isSignatureValid || isCore || isDisabled) { return null; } @@ -43,3 +44,18 @@ export function PluginDetailsSignature({ className, plugin }: Props): React.Reac ); } + +function isDisabledDueTooSignatureError(error: PluginErrorCode | undefined) { + // If the plugin is disabled due to signature error we rely on the disabled + // error message instad of the warning about the signature. + + switch (error) { + case PluginErrorCode.invalidSignature: + case PluginErrorCode.missingSignature: + case PluginErrorCode.modifiedSignature: + return true; + + default: + return false; + } +} diff --git a/public/app/features/plugins/admin/helpers.ts b/public/app/features/plugins/admin/helpers.ts index 34f08f93146..e0fca9656d7 100644 --- a/public/app/features/plugins/admin/helpers.ts +++ b/public/app/features/plugins/admin/helpers.ts @@ -1,6 +1,6 @@ import { config } from '@grafana/runtime'; import { gt } from 'semver'; -import { PluginSignatureStatus, dateTimeParse, PluginError } from '@grafana/data'; +import { PluginSignatureStatus, dateTimeParse, PluginError, PluginErrorCode } from '@grafana/data'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { Settings } from 'app/core/config'; import { CatalogPlugin, LocalPlugin, RemotePlugin } from './types'; @@ -59,11 +59,8 @@ export function mapRemoteToCatalog(plugin: RemotePlugin, error?: PluginError): C updatedAt, createdAt: publishedAt, status, - versionSignatureType, - signatureType, } = plugin; - const hasSignature = signatureType !== '' || versionSignatureType !== ''; const isDisabled = !!error; const catalogPlugin = { description, @@ -79,7 +76,7 @@ export function mapRemoteToCatalog(plugin: RemotePlugin, error?: PluginError): C orgName, popularity, publishedAt, - signature: hasSignature ? PluginSignatureStatus.valid : PluginSignatureStatus.missing, + signature: getPluginSignature({ remote: plugin, error }), updatedAt, version, hasUpdate: false, @@ -115,7 +112,7 @@ export function mapLocalToCatalog(plugin: LocalPlugin, error?: PluginError): Cat orgName: author.name, popularity: 0, publishedAt: '', - signature, + signature: getPluginSignature({ local: plugin, error }), signatureOrg, signatureType, updatedAt: updated, @@ -136,7 +133,6 @@ export function mapToCatalogPlugin(local?: LocalPlugin, remote?: RemotePlugin, e const hasUpdate = local?.hasUpdate || Boolean(remote?.version && local?.info.version && gt(remote?.version, local?.info.version)); const id = remote?.slug || local?.id || ''; - const hasRemoteSignature = remote?.signatureType || remote?.versionSignatureType; const isDisabled = !!error; let logos = { @@ -171,7 +167,7 @@ export function mapToCatalogPlugin(local?: LocalPlugin, remote?: RemotePlugin, e popularity: remote?.popularity || 0, publishedAt: remote?.createdAt || '', type: remote?.typeCode || local?.type, - signature: local?.signature || (hasRemoteSignature ? PluginSignatureStatus.valid : PluginSignatureStatus.missing), + signature: getPluginSignature({ local, remote, error }), signatureOrg: local?.signatureOrg || remote?.versionSignedByOrgName, signatureType: local?.signatureType || remote?.versionSignatureType || remote?.signatureType || undefined, updatedAt: remote?.updatedAt || local?.info.updated || '', @@ -215,6 +211,35 @@ function groupErrorsByPluginId(errors: PluginError[] = []): Record); } +function getPluginSignature(options: { + local?: LocalPlugin; + remote?: RemotePlugin; + error?: PluginError; +}): PluginSignatureStatus { + const { error, local, remote } = options; + + if (error) { + switch (error.errorCode) { + case PluginErrorCode.invalidSignature: + return PluginSignatureStatus.invalid; + case PluginErrorCode.missingSignature: + return PluginSignatureStatus.missing; + case PluginErrorCode.modifiedSignature: + return PluginSignatureStatus.modified; + } + } + + if (local?.signature) { + return local.signature; + } + + if (remote?.signatureType || remote?.versionSignatureType) { + return PluginSignatureStatus.valid; + } + + return PluginSignatureStatus.missing; +} + // Updates the core Grafana config to have the correct list available panels export const updatePanels = () => getBackendSrv() diff --git a/public/app/features/plugins/admin/pages/PluginDetails.tsx b/public/app/features/plugins/admin/pages/PluginDetails.tsx index 81758126f8b..ae4979570ed 100644 --- a/public/app/features/plugins/admin/pages/PluginDetails.tsx +++ b/public/app/features/plugins/admin/pages/PluginDetails.tsx @@ -99,8 +99,8 @@ export default function PluginDetails({ match, queryParams }: Props): JSX.Elemen {/* Active tab */} - +