2022-11-09 03:05:01 -06:00
|
|
|
import { css, cx } from '@emotion/css';
|
2023-03-14 09:38:21 -05:00
|
|
|
import React from 'react';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2023-05-04 08:17:44 -05:00
|
|
|
import { NavModelItem, GrafanaTheme2 } from '@grafana/data';
|
2022-09-01 07:23:41 -05:00
|
|
|
import { Tab, TabsBar, Icon, useStyles2, toIconName } from '@grafana/ui';
|
2020-11-03 08:29:43 -06:00
|
|
|
import { PanelHeaderMenuItem } from 'app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2022-11-09 03:05:01 -06:00
|
|
|
import { PageInfoItem } from '../Page/types';
|
|
|
|
import { PageInfo } from '../PageInfo/PageInfo';
|
2022-02-08 01:53:57 -06:00
|
|
|
import { ProBadge } from '../Upgrade/ProBadge';
|
2017-11-30 08:37:03 -06:00
|
|
|
|
2018-08-24 09:48:47 -05:00
|
|
|
export interface Props {
|
2022-07-06 10:00:56 -05:00
|
|
|
navItem: NavModelItem;
|
2022-11-09 03:05:01 -06:00
|
|
|
renderTitle?: (title: string) => React.ReactNode;
|
|
|
|
actions?: React.ReactNode;
|
|
|
|
info?: PageInfoItem[];
|
|
|
|
subTitle?: React.ReactNode;
|
2017-11-30 08:37:03 -06:00
|
|
|
}
|
|
|
|
|
2020-05-07 06:53:05 -05:00
|
|
|
const SelectNav = ({ children, customCss }: { children: NavModelItem[]; customCss: string }) => {
|
|
|
|
if (!children || children.length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-01-20 00:59:48 -06:00
|
|
|
const defaultSelectedItem = children.find((navItem) => {
|
2017-12-06 10:36:44 -06:00
|
|
|
return navItem.active === true;
|
|
|
|
});
|
|
|
|
|
2017-12-19 06:19:44 -06:00
|
|
|
return (
|
|
|
|
<div className={`gf-form-select-wrapper width-20 ${customCss}`}>
|
2020-11-03 08:29:43 -06:00
|
|
|
<div className="dropdown">
|
2022-10-14 08:57:45 -05:00
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="gf-form-input dropdown-toggle"
|
|
|
|
data-toggle="dropdown"
|
|
|
|
style={{ textAlign: 'left' }}
|
|
|
|
>
|
2020-11-03 08:29:43 -06:00
|
|
|
{defaultSelectedItem?.text}
|
2022-10-14 08:57:45 -05:00
|
|
|
</button>
|
|
|
|
<ul role="menu" className="dropdown-menu dropdown-menu--menu">
|
2020-11-03 08:29:43 -06:00
|
|
|
{children.map((navItem: NavModelItem) => {
|
|
|
|
if (navItem.hideFromTabs) {
|
|
|
|
// TODO: Rename hideFromTabs => hideFromNav
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<PanelHeaderMenuItem
|
|
|
|
key={navItem.url}
|
|
|
|
iconClassName={navItem.icon}
|
|
|
|
text={navItem.text}
|
|
|
|
href={navItem.url}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</ul>
|
|
|
|
</div>
|
2017-12-20 04:22:29 -06:00
|
|
|
</div>
|
|
|
|
);
|
2018-01-18 15:28:13 -06:00
|
|
|
};
|
2017-12-06 10:36:44 -06:00
|
|
|
|
2020-05-07 06:53:05 -05:00
|
|
|
const Navigation = ({ children }: { children: NavModelItem[] }) => {
|
|
|
|
if (!children || children.length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-01-18 11:13:01 -06:00
|
|
|
return (
|
|
|
|
<nav>
|
2020-11-18 08:36:35 -06:00
|
|
|
<SelectNav customCss="page-header__select-nav">{children}</SelectNav>
|
2020-01-15 05:54:35 -06:00
|
|
|
<TabsBar className="page-header__tabs" hideBorder={true}>
|
2020-05-07 06:53:05 -05:00
|
|
|
{children.map((child, index) => {
|
2020-01-10 03:38:43 -06:00
|
|
|
return (
|
2020-02-03 01:16:48 -06:00
|
|
|
!child.hideFromTabs && (
|
|
|
|
<Tab
|
2023-02-08 07:15:37 -06:00
|
|
|
label={child.text}
|
2020-02-03 01:16:48 -06:00
|
|
|
active={child.active}
|
|
|
|
key={`${child.url}-${index}`}
|
2022-09-12 13:09:33 -05:00
|
|
|
icon={child.icon}
|
2020-06-24 09:58:40 -05:00
|
|
|
href={child.url}
|
2022-01-26 01:15:45 -06:00
|
|
|
suffix={child.tabSuffix}
|
2020-02-03 01:16:48 -06:00
|
|
|
/>
|
|
|
|
)
|
2020-01-10 03:38:43 -06:00
|
|
|
);
|
|
|
|
})}
|
|
|
|
</TabsBar>
|
2018-01-18 11:13:01 -06:00
|
|
|
</nav>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-03-14 09:38:21 -05:00
|
|
|
export const PageHeader = ({ navItem: model, renderTitle, actions, info, subTitle }: Props) => {
|
2021-04-21 07:25:43 -05:00
|
|
|
const styles = useStyles2(getStyles);
|
2017-11-30 08:37:03 -06:00
|
|
|
|
2021-02-20 02:02:06 -06:00
|
|
|
if (!model) {
|
|
|
|
return null;
|
2018-01-18 15:28:13 -06:00
|
|
|
}
|
|
|
|
|
2022-11-09 03:05:01 -06:00
|
|
|
const renderHeader = (main: NavModelItem) => {
|
|
|
|
const marginTop = main.icon === 'grafana' ? 12 : 14;
|
|
|
|
const icon = main.icon && toIconName(main.icon);
|
2023-02-08 07:15:37 -06:00
|
|
|
const sub = subTitle ?? main.subTitle;
|
2022-11-09 03:05:01 -06:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="page-header__inner">
|
|
|
|
<span className="page-header__logo">
|
|
|
|
{icon && <Icon name={icon} size="xxxl" style={{ marginTop }} />}
|
2023-02-08 07:15:37 -06:00
|
|
|
{main.img && <img className="page-header__img" src={main.img} alt="" />}
|
2022-11-09 03:05:01 -06:00
|
|
|
</span>
|
|
|
|
|
|
|
|
<div className={cx('page-header__info-block', styles.headerText)}>
|
2023-05-04 08:17:44 -05:00
|
|
|
{renderTitle ? renderTitle(main.text) : renderHeaderTitle(main.text, main.highlightText)}
|
2022-11-09 03:05:01 -06:00
|
|
|
{info && <PageInfo info={info} />}
|
|
|
|
{sub && <div className="page-header__sub-title">{sub}</div>}
|
|
|
|
{actions && <div className={styles.actions}>{actions}</div>}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-02-20 02:02:06 -06:00
|
|
|
return (
|
|
|
|
<div className={styles.headerCanvas}>
|
2021-04-09 05:44:26 -05:00
|
|
|
<div className="page-container">
|
2021-02-20 02:02:06 -06:00
|
|
|
<div className="page-header">
|
2022-11-09 03:05:01 -06:00
|
|
|
{renderHeader(model)}
|
2022-07-06 10:00:56 -05:00
|
|
|
{model.children && model.children.length > 0 && <Navigation>{model.children}</Navigation>}
|
2021-02-20 02:02:06 -06:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
2018-01-11 10:53:06 -06:00
|
|
|
|
2023-05-04 08:17:44 -05:00
|
|
|
function renderHeaderTitle(title: string, highlightText: NavModelItem['highlightText']) {
|
|
|
|
if (!title) {
|
2021-02-20 02:02:06 -06:00
|
|
|
return null;
|
2017-11-30 08:37:03 -06:00
|
|
|
}
|
|
|
|
|
2023-05-04 08:17:44 -05:00
|
|
|
return (
|
|
|
|
<h1 className="page-header__title">
|
|
|
|
{title}
|
|
|
|
{highlightText && (
|
|
|
|
<ProBadge
|
|
|
|
text={highlightText}
|
|
|
|
className={css`
|
|
|
|
vertical-align: middle;
|
|
|
|
`}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</h1>
|
|
|
|
);
|
2017-11-30 08:37:03 -06:00
|
|
|
}
|
2021-02-20 02:02:06 -06:00
|
|
|
|
2021-05-03 02:45:54 -05:00
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
2022-11-09 03:05:01 -06:00
|
|
|
actions: css({
|
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'row',
|
|
|
|
gap: theme.spacing(1),
|
|
|
|
}),
|
|
|
|
headerText: css({
|
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'column',
|
|
|
|
gap: theme.spacing(1),
|
|
|
|
}),
|
2021-02-20 02:02:06 -06:00
|
|
|
headerCanvas: css`
|
2021-04-21 08:34:08 -05:00
|
|
|
background: ${theme.colors.background.canvas};
|
2021-02-20 02:02:06 -06:00
|
|
|
`,
|
|
|
|
});
|