PageHeader.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import React from "react";
  2. import { NavModel, NavModelItem } from "../../nav_model_srv";
  3. import classNames from "classnames";
  4. import appEvents from "app/core/app_events";
  5. export interface IProps {
  6. model: NavModel;
  7. }
  8. function TabItem(tab: NavModelItem) {
  9. if (tab.hideFromTabs) {
  10. return null;
  11. }
  12. let tabClasses = classNames({
  13. "gf-tabs-link": true,
  14. active: tab.active
  15. });
  16. return (
  17. <li className="gf-tabs-item" key={tab.url}>
  18. <a className={tabClasses} target={tab.target} href={tab.url}>
  19. <i className={tab.icon} />
  20. {tab.text}
  21. </a>
  22. </li>
  23. );
  24. }
  25. function SelectOption(navItem: NavModelItem) {
  26. if (navItem.hideFromTabs) {
  27. // TODO: Rename hideFromTabs => hideFromNav
  28. return null;
  29. }
  30. return (
  31. <option key={navItem.url} value={navItem.url}>
  32. {navItem.text}
  33. </option>
  34. );
  35. }
  36. function Navigation({ main }: { main: NavModelItem }) {
  37. return (
  38. <nav>
  39. <SelectNav customCss="page-header__select-nav" main={main} />
  40. <Tabs customCss="page-header__tabs" main={main} />
  41. </nav>
  42. );
  43. }
  44. function SelectNav({
  45. main,
  46. customCss
  47. }: {
  48. main: NavModelItem;
  49. customCss: string;
  50. }) {
  51. const defaultSelectedItem = main.children.find(navItem => {
  52. return navItem.active === true;
  53. });
  54. const gotoUrl = evt => {
  55. var element = evt.target;
  56. var url = element.options[element.selectedIndex].value;
  57. appEvents.emit("location-change", { href: url });
  58. };
  59. return (
  60. <div className={`gf-form-select-wrapper width-20 ${customCss}`}>
  61. <label
  62. className={`gf-form-select-icon ${defaultSelectedItem.icon}`}
  63. htmlFor="page-header-select-nav"
  64. />
  65. {/* Label to make it clickable */}
  66. <select
  67. className="gf-select-nav gf-form-input"
  68. defaultValue={defaultSelectedItem.url}
  69. onChange={gotoUrl}
  70. id="page-header-select-nav"
  71. >
  72. {main.children.map(SelectOption)}
  73. </select>
  74. </div>
  75. );
  76. }
  77. function Tabs({ main, customCss }: { main: NavModelItem; customCss: string }) {
  78. return (
  79. <ul className={`gf-tabs ${customCss}`}>{main.children.map(TabItem)}</ul>
  80. );
  81. }
  82. export default class PageHeader extends React.Component<IProps, any> {
  83. constructor(props) {
  84. super(props);
  85. }
  86. renderBreadcrumb(breadcrumbs) {
  87. const breadcrumbsResult = [];
  88. for (let i = 0; i < breadcrumbs.length; i++) {
  89. const bc = breadcrumbs[i];
  90. if (bc.url) {
  91. breadcrumbsResult.push(
  92. <a className="text-link" key={i} href={bc.url}>
  93. {bc.title}
  94. </a>
  95. );
  96. } else {
  97. breadcrumbsResult.push(<span key={i}> / {bc.title}</span>);
  98. }
  99. }
  100. return breadcrumbsResult;
  101. }
  102. renderHeaderTitle(main) {
  103. return (
  104. <div className="page-header__inner">
  105. <span className="page-header__logo">
  106. {main.icon && <i className={`page-header__icon ${main.icon}`} />}
  107. {main.img && <img className="page-header__img" src={main.img} />}
  108. </span>
  109. <div className="page-header__info-block">
  110. {main.text && <h1 className="page-header__title">{main.text}</h1>}
  111. {main.breadcrumbs &&
  112. main.breadcrumbs.length > 0 && (
  113. <h1 className="page-header__title">
  114. {this.renderBreadcrumb(main.breadcrumbs)}
  115. </h1>
  116. )}
  117. {main.subTitle && (
  118. <div className="page-header__sub-title">{main.subTitle}</div>
  119. )}
  120. {main.subType && (
  121. <div className="page-header__stamps">
  122. <i className={main.subType.icon} />
  123. {main.subType.text}
  124. </div>
  125. )}
  126. </div>
  127. </div>
  128. );
  129. }
  130. render() {
  131. const { model } = this.props;
  132. if (!model) {
  133. return null;
  134. }
  135. return (
  136. <div className="page-header-canvas">
  137. <div className="page-container">
  138. <div className="page-header">
  139. {this.renderHeaderTitle(model.main)}
  140. {model.main.children && <Navigation main={model.main} />}
  141. </div>
  142. </div>
  143. </div>
  144. );
  145. }
  146. }