grafana/public/app/features/plugins/admin/components/PluginDetailsHeader.tsx
Marcus Efraimsson 199cacc7b6
Plugins Catalog: Fix styling of hyperlinks (#48196)
Adds some styling (default hyperlink color and underline on hover) to 
plugin header and body hyperlinks.

Fixes #48078
2022-04-27 14:34:47 +02:00

171 lines
4.8 KiB
TypeScript

import { css, cx } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Icon, HorizontalGroup } from '@grafana/ui';
import { getLatestCompatibleVersion } from '../helpers';
import { CatalogPlugin } from '../types';
import { PluginDisabledBadge } from './Badges';
import { GetStartedWithPlugin } from './GetStartedWithPlugin';
import { InstallControls } from './InstallControls';
import { PluginDetailsHeaderDependencies } from './PluginDetailsHeaderDependencies';
import { PluginDetailsHeaderSignature } from './PluginDetailsHeaderSignature';
import { PluginLogo } from './PluginLogo';
type Props = {
currentUrl: string;
parentUrl: string;
plugin: CatalogPlugin;
};
export function PluginDetailsHeader({ plugin, currentUrl, parentUrl }: Props): React.ReactElement {
const styles = useStyles2(getStyles);
const latestCompatibleVersion = getLatestCompatibleVersion(plugin.details?.versions);
const version = plugin.installedVersion || latestCompatibleVersion?.version;
return (
<div>
<div className="page-container">
<div className={styles.headerContainer}>
<PluginLogo
alt={`${plugin.name} logo`}
src={plugin.info.logos.small}
className={css`
object-fit: contain;
width: 100%;
height: 68px;
max-width: 68px;
`}
/>
<div className={styles.headerWrapper}>
{/* Title & navigation */}
<nav className={styles.breadcrumb} aria-label="Breadcrumb">
<ol>
<li>
<a className={styles.textUnderline} href={parentUrl}>
Plugins
</a>
</li>
<li>
<a href={currentUrl} aria-current="page">
{plugin.name}
</a>
</li>
</ol>
</nav>
<div className={styles.headerInformationRow}>
{/* Org name */}
<span>{plugin.orgName}</span>
{/* Links */}
{plugin.details?.links.map((link: any) => (
<a key={link.name} href={link.url}>
{link.name}
</a>
))}
{/* Downloads */}
{plugin.downloads > 0 && (
<span>
<Icon name="cloud-download" />
{` ${new Intl.NumberFormat().format(plugin.downloads)}`}{' '}
</span>
)}
{/* Version */}
{Boolean(version) && <span>{version}</span>}
{/* Signature information */}
<PluginDetailsHeaderSignature plugin={plugin} />
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error!} />}
</div>
<PluginDetailsHeaderDependencies
plugin={plugin}
latestCompatibleVersion={latestCompatibleVersion}
className={cx(styles.headerInformationRow, styles.headerInformationRowSecondary)}
/>
<p>{plugin.description}</p>
<HorizontalGroup height="auto">
<InstallControls plugin={plugin} latestCompatibleVersion={latestCompatibleVersion} />
<GetStartedWithPlugin plugin={plugin} />
</HorizontalGroup>
</div>
</div>
</div>
</div>
);
}
export const getStyles = (theme: GrafanaTheme2) => {
return {
headerContainer: css`
display: flex;
margin-bottom: ${theme.spacing(3)};
margin-top: ${theme.spacing(3)};
min-height: 120px;
`,
headerWrapper: css`
margin-left: ${theme.spacing(3)};
`,
breadcrumb: css`
font-size: ${theme.typography.h2.fontSize};
li {
display: inline;
list-style: none;
&::after {
content: '/';
padding: 0 0.25ch;
}
&:last-child::after {
content: '';
}
}
`,
headerInformationRow: css`
display: flex;
align-items: center;
margin-top: ${theme.spacing()};
margin-bottom: ${theme.spacing()};
flex-flow: wrap;
& > * {
&::after {
content: '|';
padding: 0 ${theme.spacing()};
}
&:last-child::after {
content: '';
padding-right: 0;
}
}
font-size: ${theme.typography.h4.fontSize};
a {
&:hover {
text-decoration: underline;
}
}
`,
headerInformationRowSecondary: css`
font-size: ${theme.typography.body.fontSize};
`,
headerOrgName: css`
font-size: ${theme.typography.h4.fontSize};
`,
signature: css`
margin: ${theme.spacing(3)};
margin-bottom: 0;
`,
textUnderline: css`
text-decoration: underline;
`,
};
};