2021-02-20 16:02:06 +08:00
|
|
|
import React, { FC } from 'react';
|
2021-04-09 18:44:26 +08:00
|
|
|
import { css } from '@emotion/css';
|
2021-02-20 16:02:06 +08:00
|
|
|
import { Tab, TabsBar, Icon, IconName, useStyles } from '@grafana/ui';
|
|
|
|
|
import { NavModel, NavModelItem, NavModelBreadcrumb, GrafanaTheme } from '@grafana/data';
|
2020-11-03 22:29:43 +08:00
|
|
|
import { PanelHeaderMenuItem } from 'app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem';
|
2017-11-30 22:37:03 +08:00
|
|
|
|
2018-08-24 22:48:47 +08:00
|
|
|
export interface Props {
|
2017-11-30 22:37:03 +08:00
|
|
|
model: NavModel;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-07 19:53:05 +08:00
|
|
|
const SelectNav = ({ children, customCss }: { children: NavModelItem[]; customCss: string }) => {
|
|
|
|
|
if (!children || children.length === 0) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-20 14:59:48 +08:00
|
|
|
const defaultSelectedItem = children.find((navItem) => {
|
2017-12-07 00:36:44 +08:00
|
|
|
return navItem.active === true;
|
|
|
|
|
});
|
|
|
|
|
|
2017-12-19 20:19:44 +08:00
|
|
|
return (
|
|
|
|
|
<div className={`gf-form-select-wrapper width-20 ${customCss}`}>
|
2020-11-03 22:29:43 +08:00
|
|
|
<div className="dropdown">
|
|
|
|
|
<div className="gf-form-input dropdown-toggle" data-toggle="dropdown">
|
|
|
|
|
{defaultSelectedItem?.text}
|
|
|
|
|
</div>
|
|
|
|
|
<ul className="dropdown-menu dropdown-menu--menu">
|
|
|
|
|
{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 18:22:29 +08:00
|
|
|
</div>
|
|
|
|
|
);
|
2018-01-19 05:28:13 +08:00
|
|
|
};
|
2017-12-07 00:36:44 +08:00
|
|
|
|
2020-05-07 19:53:05 +08:00
|
|
|
const Navigation = ({ children }: { children: NavModelItem[] }) => {
|
|
|
|
|
if (!children || children.length === 0) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-19 01:13:01 +08:00
|
|
|
return (
|
|
|
|
|
<nav>
|
2020-11-18 22:36:35 +08:00
|
|
|
<SelectNav customCss="page-header__select-nav">{children}</SelectNav>
|
2020-01-15 19:54:35 +08:00
|
|
|
<TabsBar className="page-header__tabs" hideBorder={true}>
|
2020-05-07 19:53:05 +08:00
|
|
|
{children.map((child, index) => {
|
2020-01-10 17:38:43 +08:00
|
|
|
return (
|
2020-02-03 15:16:48 +08:00
|
|
|
!child.hideFromTabs && (
|
|
|
|
|
<Tab
|
|
|
|
|
label={child.text}
|
|
|
|
|
active={child.active}
|
|
|
|
|
key={`${child.url}-${index}`}
|
@grafana/ui: Create Icon component and replace part of the icons (#23402)
* Part1: Unicons implementation (#23197)
* Create a new Icon component
* Update icons in main sidebar
* Update icons in Useful links and in react components on main site
* Update icons in Useful links and in main top navigation
* Adjust sizing
* Update panel navigation and timepicker
* Update icons in Panel menu
* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)
* Update icons in add panel widget
* Resolve merge conflict
* Fix part of the test errors and type errors
* Fix storybook errors
* Update getAvailableIcons import in storybook knobs
* Fix import path
* Fix SyntaxError: Cannot use import statement outside a module in test environment error
* Remove dynamic imports
* Remove types as using @ts-ignore
* Update snapshot test
* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax
* Remove color prop from icon, remove color implemetation in mono icons
* Update navbar styling
* Move toPascalCase to utils/string
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
* Resolve type errors resulted from merge
* Part2: Unicons implementation (#23266)
* Create a new Icon component
* Update icons in main sidebar
* Update icons in Useful links and in react components on main site
* Update icons in Useful links and in main top navigation
* Adjust sizing
* Update panel navigation and timepicker
* Update icons in Panel menu
* Update icons in add panel widget
* Resolve merge conflict
* Fix part of the test errors and type errors
* Fix storybook errors
* Update getAvailableIcons import in storybook knobs
* Fix import path
* Fix SyntaxError: Cannot use import statement outside a module in test environment error
* Remove dynamic imports
* Remove types as using @ts-ignore
* Update snapshot test
* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax
* Implment icons in Tabs
* Implement icons in search items and empty list
* Update buttons
* Update button-related snapshot tests
* Update icons in modals and page headers
* Create anfular wrapper and update all icons on search screen
* Update sizing, remove colors, update snapshot tests
* Remove color prop from icon, remove color implemetation in mono icons
* Remove color props from monochrome icons
* Complete update of icons for search screen
* Update icons for infor tooltips, playlist, permissions
* Support temporarly font awesome icons used in enterprise grafana
* Part1: Unicons implementation (#23197)
* Create a new Icon component
* Update icons in main sidebar
* Update icons in Useful links and in react components on main site
* Update icons in Useful links and in main top navigation
* Adjust sizing
* Update panel navigation and timepicker
* Update icons in Panel menu
* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)
* Update icons in add panel widget
* Resolve merge conflict
* Fix part of the test errors and type errors
* Fix storybook errors
* Update getAvailableIcons import in storybook knobs
* Fix import path
* Fix SyntaxError: Cannot use import statement outside a module in test environment error
* Remove dynamic imports
* Remove types as using @ts-ignore
* Update snapshot test
* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax
* Remove color prop from icon, remove color implemetation in mono icons
* Update navbar styling
* Move toPascalCase to utils/string
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
* Icons update
* Add optional chaining to for isFontAwesome variable
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
* Part3: Unicons implementation (#23356)
* Create a new Icon component
* Update icons in main sidebar
* Update icons in Useful links and in react components on main site
* Update icons in Useful links and in main top navigation
* Adjust sizing
* Update panel navigation and timepicker
* Update icons in Panel menu
* Update icons in add panel widget
* Resolve merge conflict
* Fix part of the test errors and type errors
* Fix storybook errors
* Update getAvailableIcons import in storybook knobs
* Fix import path
* Fix SyntaxError: Cannot use import statement outside a module in test environment error
* Remove dynamic imports
* Remove types as using @ts-ignore
* Update snapshot test
* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax
* Implment icons in Tabs
* Implement icons in search items and empty list
* Update buttons
* Update button-related snapshot tests
* Update icons in modals and page headers
* Create anfular wrapper and update all icons on search screen
* Update sizing, remove colors, update snapshot tests
* Remove color prop from icon, remove color implemetation in mono icons
* Remove color props from monochrome icons
* Complete update of icons for search screen
* Update icons for infor tooltips, playlist, permissions
* Support temporarly font awesome icons used in enterprise grafana
* Part1: Unicons implementation (#23197)
* Create a new Icon component
* Update icons in main sidebar
* Update icons in Useful links and in react components on main site
* Update icons in Useful links and in main top navigation
* Adjust sizing
* Update panel navigation and timepicker
* Update icons in Panel menu
* NewPanelEditor: Fixed so that test alert rule works in new edit mode (#23179)
* Update icons in add panel widget
* Resolve merge conflict
* Fix part of the test errors and type errors
* Fix storybook errors
* Update getAvailableIcons import in storybook knobs
* Fix import path
* Fix SyntaxError: Cannot use import statement outside a module in test environment error
* Remove dynamic imports
* Remove types as using @ts-ignore
* Update snapshot test
* Add @iconscout/react-unicons to the shouldExclude list as it is blundled with es2015 syntax
* Remove color prop from icon, remove color implemetation in mono icons
* Update navbar styling
* Move toPascalCase to utils/string
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
* Update icons in Explore
* Update icons in alerting
* Update + and x buttons
* Update icons in configurations and settings
* Update close icons
* Update icons in rich history
* Update alert messages
* Add optional chaining to for isFontAwesome variable
* Remove icon mock, set up jest.config
* Fix navbar plus icon
* Fir enable-bacground to enableBackgournd
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
* Merge remote branch origin master to icons-unicons
* Revert "Merge remote branch origin master to icons-unicons"
This reverts commit 3f25d50a39a940883fefe73ce51219139c1ed37f.
* Size-up dashnav icons
* Fix alerting icons, panel headers, update tests
* Fix typecheck error
* Adjustments - add panel icon, spacing
* Set TerserPlugin sourceMap to false to prevent running out of memory when publishing storybook
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-04-08 20:33:31 +08:00
|
|
|
icon={child.icon as IconName}
|
2020-06-24 22:58:40 +08:00
|
|
|
href={child.url}
|
2020-02-03 15:16:48 +08:00
|
|
|
/>
|
|
|
|
|
)
|
2020-01-10 17:38:43 +08:00
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</TabsBar>
|
2018-01-19 01:13:01 +08:00
|
|
|
</nav>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-09 18:44:26 +08:00
|
|
|
export const PageHeader: FC<Props> = ({ model }) => {
|
2021-02-20 16:02:06 +08:00
|
|
|
const styles = useStyles(getStyles);
|
2017-11-30 22:37:03 +08:00
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
if (!model) {
|
|
|
|
|
return null;
|
2018-01-19 05:28:13 +08:00
|
|
|
}
|
|
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
const main = model.main;
|
|
|
|
|
const children = main.children;
|
2018-01-12 00:53:06 +08:00
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
return (
|
|
|
|
|
<div className={styles.headerCanvas}>
|
2021-04-09 18:44:26 +08:00
|
|
|
<div className="page-container">
|
2021-02-20 16:02:06 +08:00
|
|
|
<div className="page-header">
|
|
|
|
|
{renderHeaderTitle(main)}
|
|
|
|
|
{children && children.length && <Navigation>{children}</Navigation>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
2018-01-12 00:53:06 +08:00
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
function renderHeaderTitle(main: NavModelItem) {
|
|
|
|
|
const marginTop = main.icon === 'grafana' ? 12 : 14;
|
2017-12-08 00:29:13 +08:00
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
return (
|
|
|
|
|
<div className="page-header__inner">
|
|
|
|
|
<span className="page-header__logo">
|
|
|
|
|
{main.icon && <Icon name={main.icon as IconName} size="xxxl" style={{ marginTop }} />}
|
|
|
|
|
{main.img && <img className="page-header__img" src={main.img} alt={`logo of ${main.text}`} />}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<div className="page-header__info-block">
|
|
|
|
|
{renderTitle(main.text, main.breadcrumbs ?? [])}
|
|
|
|
|
{main.subTitle && <div className="page-header__sub-title">{main.subTitle}</div>}
|
2017-11-30 22:37:03 +08:00
|
|
|
</div>
|
2021-02-20 16:02:06 +08:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderTitle(title: string, breadcrumbs: NavModelBreadcrumb[]) {
|
|
|
|
|
if (!title && (!breadcrumbs || breadcrumbs.length === 0)) {
|
|
|
|
|
return null;
|
2017-11-30 22:37:03 +08:00
|
|
|
}
|
|
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
if (!breadcrumbs || breadcrumbs.length === 0) {
|
|
|
|
|
return <h1 className="page-header__title">{title}</h1>;
|
|
|
|
|
}
|
2017-12-13 20:51:52 +08:00
|
|
|
|
2021-02-20 16:02:06 +08:00
|
|
|
const breadcrumbsResult = [];
|
|
|
|
|
for (const bc of breadcrumbs) {
|
|
|
|
|
if (bc.url) {
|
|
|
|
|
breadcrumbsResult.push(
|
|
|
|
|
<a className="text-link" key={breadcrumbsResult.length} href={bc.url}>
|
|
|
|
|
{bc.title}
|
|
|
|
|
</a>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
breadcrumbsResult.push(<span key={breadcrumbsResult.length}> / {bc.title}</span>);
|
2017-12-13 20:51:52 +08:00
|
|
|
}
|
2017-11-30 22:37:03 +08:00
|
|
|
}
|
2021-02-20 16:02:06 +08:00
|
|
|
breadcrumbsResult.push(<span key={breadcrumbs.length + 1}> / {title}</span>);
|
|
|
|
|
|
|
|
|
|
return <h1 className="page-header__title">{breadcrumbsResult}</h1>;
|
2017-11-30 22:37:03 +08:00
|
|
|
}
|
2021-02-20 16:02:06 +08:00
|
|
|
|
|
|
|
|
const getStyles = (theme: GrafanaTheme) => ({
|
|
|
|
|
headerCanvas: css`
|
|
|
|
|
background: ${theme.colors.bg2};
|
|
|
|
|
border-bottom: 1px solid ${theme.colors.border1};
|
|
|
|
|
`,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export default PageHeader;
|