Plugins: Display custom deprecation message if available (#75942)

* feat: display the deprecation context for a plugin if it is available

* Update public/app/features/plugins/admin/components/PluginDetailsDeprecatedWarning.tsx

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>

* feat: only extend the basic message with custom context

---------

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
Levente Balogh
2023-10-04 14:30:03 +02:00
committed by GitHub
parent 9350e8bee5
commit e7c1e5e4c9
4 changed files with 29 additions and 6 deletions

View File

@ -25,6 +25,7 @@ export async function getPluginDetails(id: string): Promise<CatalogPluginDetails
links: local?.info.links || remote?.json?.info.links || [], links: local?.info.links || remote?.json?.info.links || [],
readme: localReadme || remote?.readme, readme: localReadme || remote?.readme,
versions, versions,
statusContext: remote?.statusContext ?? '',
}; };
} }

View File

@ -13,13 +13,16 @@ export function PluginDetailsDeprecatedWarning(props: Props): React.ReactElement
const { className, plugin } = props; const { className, plugin } = props;
const [dismissed, setDismissed] = useState(false); const [dismissed, setDismissed] = useState(false);
const isWarningVisible = plugin.isDeprecated && !dismissed; const isWarningVisible = plugin.isDeprecated && !dismissed;
let deprecationMessage = `This ${plugin.type} plugin is deprecated and has been removed from the catalog. No further updates will be made to the
plugin.`;
if (plugin.details?.statusContext) {
deprecationMessage += ` More information: ${plugin.details.statusContext}`;
}
return isWarningVisible ? ( return isWarningVisible ? (
<Alert severity="warning" title="Deprecated" className={className} onRemove={() => setDismissed(true)}> <Alert severity="warning" title="Deprecated" className={className} onRemove={() => setDismissed(true)}>
<p> <p>{deprecationMessage}</p>
This {plugin.type} plugin is deprecated and removed from the catalog. No further updates will be made to the
plugin.
</p>
</Alert> </Alert>
) : null; ) : null;
} }

View File

@ -752,7 +752,7 @@ describe('Plugin details page', () => {
}); });
await waitFor(() => await waitFor(() =>
expect(queryByText(/plugin is deprecated and removed from the catalog/i)).toBeInTheDocument() expect(queryByText(/plugin is deprecated and has been removed from the catalog/i)).toBeInTheDocument()
); );
}); });
@ -764,9 +764,26 @@ describe('Plugin details page', () => {
}); });
await waitFor(() => await waitFor(() =>
expect(queryByText(/plugin is deprecated and removed from the catalog/i)).not.toBeInTheDocument() expect(queryByText(/plugin is deprecated and has been removed from the catalog/i)).not.toBeInTheDocument()
); );
}); });
it('should display a custom deprecation message if the plugin has it set', async () => {
const statusContext = 'A detailed explanation of why this plugin is deprecated.';
const { queryByText } = renderPluginDetails({
id,
isInstalled: true,
isDeprecated: true,
details: {
statusContext,
links: [],
},
});
const re = new RegExp(`No further updates will be made to the plugin. More information: ${statusContext}`, 'i');
await waitFor(() => expect(queryByText(re)).toBeInTheDocument());
});
}); });
describe('viewed as user without grafana admin permissions', () => { describe('viewed as user without grafana admin permissions', () => {

View File

@ -70,6 +70,7 @@ export interface CatalogPluginDetails {
}>; }>;
grafanaDependency?: string; grafanaDependency?: string;
pluginDependencies?: PluginDependencies['plugins']; pluginDependencies?: PluginDependencies['plugins'];
statusContext?: string;
} }
export interface CatalogPluginInfo { export interface CatalogPluginInfo {
@ -113,6 +114,7 @@ export type RemotePlugin = {
signatureType: PluginSignatureType | ''; signatureType: PluginSignatureType | '';
slug: string; slug: string;
status: RemotePluginStatus; status: RemotePluginStatus;
statusContext?: string;
typeCode: PluginType; typeCode: PluginType;
typeId: number; typeId: number;
typeName: string; typeName: string;