LoginLayout: allow providing custom branding (#54787)

* Branding: Customise values

* Branding: Customise loginLogo

* Branding: Add settings type

* Branding: Allow empty subtitle

* Branding: Allow custom footer links

* Branding: Allow empty subtitle
This commit is contained in:
Alex Khomenko 2022-09-12 12:24:45 +03:00 committed by GitHub
parent cc5f8b9180
commit 8aa80078cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 13 deletions

View File

@ -9,8 +9,8 @@ export interface BrandComponentProps {
children?: JSX.Element | JSX.Element[]; children?: JSX.Element | JSX.Element[];
} }
const LoginLogo: FC<BrandComponentProps> = ({ className }) => { export const LoginLogo: FC<BrandComponentProps & { logo?: string }> = ({ className, logo }) => {
return <img className={className} src="public/img/grafana_icon.svg" alt="Grafana" />; return <img className={className} src={`${logo ? logo : 'public/img/grafana_icon.svg'}`} alt="Grafana" />;
}; };
const LoginBackground: FC<BrandComponentProps> = ({ className, children }) => { const LoginBackground: FC<BrandComponentProps> = ({ className, children }) => {

View File

@ -0,0 +1,15 @@
import { FooterLink } from '../Footer/Footer';
export interface BrandingSettings {
footerLinks: FooterLink[] | null;
appTitle: string;
loginSubtitle: string;
loginTitle: string;
loginLogo: string;
loginBackground: string;
loginBoxBackground: string;
menuLogo: string;
favIcon: string;
loadingLogo: string;
appleTouchIcon: string;
}

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { Icon, IconName } from '@grafana/ui'; import { Icon, IconName } from '@grafana/ui';
@ -82,8 +82,13 @@ export function setVersionLinkFn(fn: typeof getFooterLinks) {
getVersionLinks = fn; getVersionLinks = fn;
} }
export const Footer: FC = React.memo(() => { export interface Props {
const links = getFooterLinks().concat(getVersionLinks()); /** Link overrides to show specific links in the UI */
customLinks?: FooterLink[] | null;
}
export const Footer = React.memo(({ customLinks }: Props) => {
const links = (customLinks || getFooterLinks()).concat(getVersionLinks());
return ( return (
<footer className="footer"> <footer className="footer">

View File

@ -5,6 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, styleMixins } from '@grafana/ui'; import { useStyles2, styleMixins } from '@grafana/ui';
import { Branding } from '../Branding/Branding'; import { Branding } from '../Branding/Branding';
import { BrandingSettings } from '../Branding/types';
import { Footer } from '../Footer/Footer'; import { Footer } from '../Footer/Footer';
interface InnerBoxProps { interface InnerBoxProps {
@ -15,26 +16,36 @@ export const InnerBox: FC<InnerBoxProps> = ({ children, enterAnimation = true })
return <div className={cx(loginStyles.loginInnerBox, enterAnimation && loginStyles.enterAnimation)}>{children}</div>; return <div className={cx(loginStyles.loginInnerBox, enterAnimation && loginStyles.enterAnimation)}>{children}</div>;
}; };
export const LoginLayout: FC = ({ children }) => { export interface LoginLayoutProps {
/** Custom branding settings that can be used e.g. for previewing the Login page changes */
branding?: BrandingSettings;
}
export const LoginLayout: FC<LoginLayoutProps> = ({ children, branding }) => {
const loginStyles = useStyles2(getLoginStyles); const loginStyles = useStyles2(getLoginStyles);
const subTitle = Branding.GetLoginSubTitle();
const [startAnim, setStartAnim] = useState(false); const [startAnim, setStartAnim] = useState(false);
const subTitle = branding?.loginSubtitle ?? Branding.GetLoginSubTitle();
const loginTitle = branding?.loginTitle ?? Branding.LoginTitle;
const loginBoxBackground = branding?.loginBoxBackground || Branding.LoginBoxBackground();
const loginLogo = branding?.loginLogo;
useEffect(() => setStartAnim(true), []); useEffect(() => setStartAnim(true), []);
return ( return (
<Branding.LoginBackground className={cx(loginStyles.container, startAnim && loginStyles.loginAnim)}> <Branding.LoginBackground
<div className={cx(loginStyles.loginContent, Branding.LoginBoxBackground(), 'login-content-box')}> className={cx(loginStyles.container, startAnim && loginStyles.loginAnim, branding?.loginBackground)}
>
<div className={cx(loginStyles.loginContent, loginBoxBackground, 'login-content-box')}>
<div className={loginStyles.loginLogoWrapper}> <div className={loginStyles.loginLogoWrapper}>
<Branding.LoginLogo className={loginStyles.loginLogo} /> <Branding.LoginLogo className={loginStyles.loginLogo} logo={loginLogo} />
<div className={loginStyles.titleWrapper}> <div className={loginStyles.titleWrapper}>
<h1 className={loginStyles.mainTitle}>{Branding.LoginTitle}</h1> <h1 className={loginStyles.mainTitle}>{loginTitle}</h1>
{subTitle && <h3 className={loginStyles.subTitle}>{Branding.GetLoginSubTitle()}</h3>} {subTitle && <h3 className={loginStyles.subTitle}>{subTitle}</h3>}
</div> </div>
</div> </div>
<div className={loginStyles.loginOuterBox}>{children}</div> <div className={loginStyles.loginOuterBox}>{children}</div>
</div> </div>
<Footer /> <Footer customLinks={branding?.footerLinks} />
</Branding.LoginBackground> </Branding.LoginBackground>
); );
}; };