mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
Catalog: Add update text to PluginListCard (#39087)
* feat(catalog): add update info to PluginListCard * refactor(catalog): use IconName enum and minor styling changes to PluginHeaderDependencies * fix(catalog): add a semver range to grafanaVersion for dependency checks in InstallControls
This commit is contained in:
parent
cbf16bebc6
commit
c9620b2202
@ -21,9 +21,16 @@ export async function getPluginDetails(id: string): Promise<CatalogPluginDetails
|
||||
const isInstalled = Boolean(local);
|
||||
const [remote, versions] = await Promise.all([getRemotePlugin(id, isInstalled), getPluginVersions(id)]);
|
||||
const dependencies = remote?.json?.dependencies;
|
||||
// Prepend semver range when we fallback to grafanaVersion (deprecated in favour of grafanaDependency)
|
||||
// otherwise plugins cannot be installed.
|
||||
const grafanaDependency = dependencies?.grafanaDependency
|
||||
? dependencies?.grafanaDependency
|
||||
: dependencies?.grafanaVersion
|
||||
? `>=${dependencies?.grafanaVersion}`
|
||||
: '';
|
||||
|
||||
return {
|
||||
grafanaDependency: dependencies?.grafanaDependency || dependencies?.grafanaVersion || '',
|
||||
grafanaDependency,
|
||||
pluginDependencies: dependencies?.plugins || [],
|
||||
links: remote?.json?.info.links || local?.info.links || [],
|
||||
readme: remote?.readme,
|
||||
|
@ -2,22 +2,13 @@ import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2, Icon } from '@grafana/ui';
|
||||
import { CatalogPlugin } from '../types';
|
||||
import { CatalogPlugin, IconName } from '../types';
|
||||
|
||||
type Props = {
|
||||
plugin: CatalogPlugin;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const PluginIconClassName: Record<string, string> = {
|
||||
datasource: 'gicon gicon-datasources',
|
||||
panel: 'icon-gf icon-gf-panel',
|
||||
app: 'icon-gf icon-gf-apps',
|
||||
page: 'icon-gf icon-gf-endpoint-tiny',
|
||||
dashboard: 'gicon gicon-dashboard',
|
||||
default: 'icon-gf icon-gf-apps',
|
||||
};
|
||||
|
||||
export function PluginDetailsHeaderDependencies({ plugin, className }: Props): React.ReactElement | null {
|
||||
const styles = useStyles2(getStyles);
|
||||
const pluginDependencies = plugin.details?.pluginDependencies;
|
||||
@ -30,12 +21,12 @@ export function PluginDetailsHeaderDependencies({ plugin, className }: Props): R
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={styles.textBold}>Dependencies:</div>
|
||||
<div className={styles.dependencyTitle}>Dependencies:</div>
|
||||
|
||||
{/* Grafana dependency */}
|
||||
{Boolean(grafanaDependency) && (
|
||||
<div>
|
||||
<Icon name="grafana" />
|
||||
<Icon name="grafana" className={styles.icon} />
|
||||
Grafana {grafanaDependency}
|
||||
</div>
|
||||
)}
|
||||
@ -46,7 +37,7 @@ export function PluginDetailsHeaderDependencies({ plugin, className }: Props): R
|
||||
{pluginDependencies.map((p) => {
|
||||
return (
|
||||
<span key={p.name}>
|
||||
<i className={PluginIconClassName[p.type] || PluginIconClassName.default} />
|
||||
<Icon name={IconName[p.type]} className={styles.icon} />
|
||||
{p.name} {p.version}
|
||||
</span>
|
||||
);
|
||||
@ -59,8 +50,18 @@ export function PluginDetailsHeaderDependencies({ plugin, className }: Props): R
|
||||
|
||||
export const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
textBold: css`
|
||||
dependencyTitle: css`
|
||||
font-weight: ${theme.typography.fontWeightBold};
|
||||
margin-right: ${theme.spacing(0.5)};
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
padding: 0;
|
||||
}
|
||||
`,
|
||||
icon: css`
|
||||
color: ${theme.colors.text.secondary};
|
||||
margin-right: ${theme.spacing(0.5)};
|
||||
`,
|
||||
};
|
||||
};
|
||||
|
@ -1,31 +1,23 @@
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { Icon, useStyles2, CardContainer, VerticalGroup } from '@grafana/ui';
|
||||
import { Icon, useStyles2, CardContainer, HorizontalGroup, VerticalGroup, Tooltip } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { CatalogPlugin } from '../types';
|
||||
import { CatalogPlugin, IconName } from '../types';
|
||||
import { PluginLogo } from './PluginLogo';
|
||||
import { PluginListBadges } from './PluginListBadges';
|
||||
|
||||
const LOGO_SIZE = '48px';
|
||||
|
||||
enum IconName {
|
||||
app = 'apps',
|
||||
datasource = 'database',
|
||||
panel = 'credit-card',
|
||||
renderer = 'pen',
|
||||
}
|
||||
|
||||
type PluginListCardProps = {
|
||||
plugin: CatalogPlugin;
|
||||
pathName: string;
|
||||
};
|
||||
|
||||
export function PluginListCard({ plugin, pathName }: PluginListCardProps) {
|
||||
const { name, id, orgName, type } = plugin;
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<CardContainer href={`${pathName}/${id}`} className={styles.cardContainer}>
|
||||
<CardContainer href={`${pathName}/${plugin.id}`} className={styles.cardContainer}>
|
||||
<VerticalGroup spacing="md">
|
||||
<div className={styles.headerWrap}>
|
||||
<PluginLogo
|
||||
@ -34,15 +26,22 @@ export function PluginListCard({ plugin, pathName }: PluginListCardProps) {
|
||||
className={styles.image}
|
||||
height={LOGO_SIZE}
|
||||
/>
|
||||
<h3 className={styles.name}>{name}</h3>
|
||||
{type && (
|
||||
<h3 className={styles.name}>{plugin.name}</h3>
|
||||
{plugin.type && (
|
||||
<div className={styles.icon}>
|
||||
<Icon name={IconName[type]} aria-label={`${type} plugin icon`} />
|
||||
<Icon name={IconName[plugin.type]} aria-label={`${plugin.type} plugin icon`} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<p className={styles.orgName}>By {orgName}</p>
|
||||
<PluginListBadges plugin={plugin} />
|
||||
<p className={styles.orgName}>By {plugin.orgName}</p>
|
||||
<HorizontalGroup align="center">
|
||||
<PluginListBadges plugin={plugin} />
|
||||
{plugin.hasUpdate && !plugin.isCore ? (
|
||||
<Tooltip content={plugin.version}>
|
||||
<p className={styles.hasUpdate}>Update available!</p>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</CardContainer>
|
||||
);
|
||||
@ -78,4 +77,9 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
color: ${theme.colors.text.secondary};
|
||||
margin-bottom: 0;
|
||||
`,
|
||||
hasUpdate: css`
|
||||
color: ${theme.colors.text.secondary};
|
||||
font-size: ${theme.typography.bodySmall.fontSize};
|
||||
margin-bottom: 0;
|
||||
`,
|
||||
});
|
||||
|
@ -13,6 +13,13 @@ export enum PluginAdminRoutes {
|
||||
DetailsAdmin = 'plugins-details-admin',
|
||||
}
|
||||
|
||||
export enum IconName {
|
||||
app = 'apps',
|
||||
datasource = 'database',
|
||||
panel = 'credit-card',
|
||||
renderer = 'pen',
|
||||
}
|
||||
|
||||
export interface CatalogPlugin {
|
||||
description: string;
|
||||
downloads: number;
|
||||
|
Loading…
Reference in New Issue
Block a user