Files
Hugo Häggmark 2b8c74de2e i18n: removes useTranslate hook (#106556)
* i18n: removes useTranslate hook

* chore: fix duplicate imports

* chore: fix import sorting and hook dependencies
2025-06-12 11:03:52 +02:00

172 lines
4.0 KiB
TypeScript

import { css } from '@emotion/css';
import { memo } from 'react';
import { GrafanaTheme2, LinkTarget } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { Icon, IconName, useStyles2 } from '@grafana/ui';
export interface FooterLink {
target: LinkTarget;
text: string;
id: string;
icon?: IconName;
url?: string;
}
export let getFooterLinks = (): FooterLink[] => {
return [
{
target: '_blank',
id: 'documentation',
text: t('nav.help/documentation', 'Documentation'),
icon: 'document-info',
url: 'https://grafana.com/docs/grafana/latest/?utm_source=grafana_footer',
},
{
target: '_blank',
id: 'support',
text: t('nav.help/support', 'Support'),
icon: 'question-circle',
url: 'https://grafana.com/products/enterprise/?utm_source=grafana_footer',
},
{
target: '_blank',
id: 'community',
text: t('nav.help/community', 'Community'),
icon: 'comments-alt',
url: 'https://community.grafana.com/?utm_source=grafana_footer',
},
];
};
export function getVersionMeta(version: string) {
const isBeta = version.includes('-beta');
return {
hasReleaseNotes: true,
isBeta,
};
}
export function getVersionLinks(hideEdition?: boolean): FooterLink[] {
const { buildInfo, licenseInfo } = config;
const links: FooterLink[] = [];
const stateInfo = licenseInfo.stateInfo ? ` (${licenseInfo.stateInfo})` : '';
if (!hideEdition) {
links.push({
target: '_blank',
id: 'license',
text: `${buildInfo.edition}${stateInfo}`,
url: licenseInfo.licenseUrl,
});
}
if (buildInfo.hideVersion) {
return links;
}
const { hasReleaseNotes } = getVersionMeta(buildInfo.version);
links.push({
target: '_blank',
id: 'version',
text: buildInfo.versionString,
url: hasReleaseNotes ? `https://github.com/grafana/grafana/blob/main/CHANGELOG.md` : undefined,
});
if (buildInfo.hasUpdate) {
links.push({
target: '_blank',
id: 'updateVersion',
text: `New version available!`,
icon: 'download-alt',
url: 'https://grafana.com/grafana/download?utm_source=grafana_footer',
});
}
return links;
}
export function setFooterLinksFn(fn: typeof getFooterLinks) {
getFooterLinks = fn;
}
export interface Props {
/** Link overrides to show specific links in the UI */
customLinks?: FooterLink[] | null;
hideEdition?: boolean;
}
export const Footer = memo(({ customLinks, hideEdition }: Props) => {
const links = (customLinks || getFooterLinks()).concat(getVersionLinks(hideEdition));
const styles = useStyles2(getStyles);
return (
<footer className={styles.footer}>
<div className="text-center">
<ul className={styles.list}>
{links.map((link, index) => (
<li className={styles.listItem} key={index}>
<FooterItem item={link} />
</li>
))}
</ul>
</div>
</footer>
);
});
Footer.displayName = 'Footer';
function FooterItem({ item }: { item: FooterLink }) {
const content = item.url ? (
<a href={item.url} target={item.target} rel="noopener noreferrer" id={item.id}>
{item.text}
</a>
) : (
item.text
);
return (
<>
{item.icon && <Icon name={item.icon} />} {content}
</>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
footer: css({
...theme.typography.bodySmall,
color: theme.colors.text.primary,
display: 'block',
padding: theme.spacing(2, 0),
position: 'relative',
width: '98%',
'a:hover': {
color: theme.colors.text.maxContrast,
textDecoration: 'underline',
},
[theme.breakpoints.down('md')]: {
display: 'none',
},
}),
list: css({
listStyle: 'none',
}),
listItem: css({
display: 'inline-block',
'&:after': {
content: "' | '",
padding: theme.spacing(0, 1),
},
'&:last-child:after': {
content: "''",
paddingLeft: 0,
},
}),
});