header.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import * as React from 'react';
  2. import {InjectedRouter} from 'react-router/lib/Router';
  3. import styled from '@emotion/styled';
  4. import {navigateTo} from 'app/actionCreators/navigation';
  5. import Feature from 'app/components/acl/feature';
  6. import Button from 'app/components/button';
  7. import ButtonBar from 'app/components/buttonBar';
  8. import CreateAlertButton from 'app/components/createAlertButton';
  9. import GlobalSelectionLink from 'app/components/globalSelectionLink';
  10. import * as Layout from 'app/components/layouts/thirds';
  11. import {IconSettings} from 'app/icons';
  12. import {t} from 'app/locale';
  13. import space from 'app/styles/space';
  14. import {Organization} from 'app/types';
  15. type Props = {
  16. router: InjectedRouter;
  17. organization: Organization;
  18. activeTab: 'stream' | 'rules';
  19. };
  20. const AlertHeader = ({router, organization, activeTab}: Props) => {
  21. /**
  22. * Incidents list is currently at the organization level, but the link needs to
  23. * go down to a specific project scope.
  24. */
  25. const handleNavigateToSettings = (e: React.MouseEvent) => {
  26. e.preventDefault();
  27. navigateTo(`/settings/${organization.slug}/projects/:projectId/alerts/`, router);
  28. };
  29. const alertRulesLink = (
  30. <li className={activeTab === 'rules' ? 'active' : ''}>
  31. <GlobalSelectionLink to={`/organizations/${organization.slug}/alerts/rules/`}>
  32. {t('Alert Rules')}
  33. </GlobalSelectionLink>
  34. </li>
  35. );
  36. return (
  37. <React.Fragment>
  38. <BorderlessHeader>
  39. <StyledLayoutHeaderContent>
  40. <StyledLayoutTitle>{t('Alerts')}</StyledLayoutTitle>
  41. </StyledLayoutHeaderContent>
  42. <Layout.HeaderActions>
  43. <Actions gap={1}>
  44. <CreateAlertButton
  45. organization={organization}
  46. iconProps={{size: 'sm'}}
  47. priority="primary"
  48. referrer="alert_stream"
  49. showPermissionGuide
  50. >
  51. {t('Create Alert Rule')}
  52. </CreateAlertButton>
  53. <Button
  54. onClick={handleNavigateToSettings}
  55. href="#"
  56. icon={<IconSettings size="sm" />}
  57. aria-label="Settings"
  58. />
  59. </Actions>
  60. </Layout.HeaderActions>
  61. </BorderlessHeader>
  62. <TabLayoutHeader>
  63. <Layout.HeaderNavTabs underlined>
  64. <Feature features={['alert-details-redesign']} organization={organization}>
  65. {({hasFeature}) =>
  66. !hasFeature ? (
  67. <React.Fragment>
  68. <Feature features={['incidents']} organization={organization}>
  69. <li className={activeTab === 'stream' ? 'active' : ''}>
  70. <GlobalSelectionLink
  71. to={`/organizations/${organization.slug}/alerts/`}
  72. >
  73. {t('Metric Alerts')}
  74. </GlobalSelectionLink>
  75. </li>
  76. </Feature>
  77. {alertRulesLink}
  78. </React.Fragment>
  79. ) : (
  80. <React.Fragment>
  81. {alertRulesLink}
  82. <li className={activeTab === 'stream' ? 'active' : ''}>
  83. <GlobalSelectionLink
  84. to={`/organizations/${organization.slug}/alerts/`}
  85. >
  86. {t('History')}
  87. </GlobalSelectionLink>
  88. </li>
  89. </React.Fragment>
  90. )
  91. }
  92. </Feature>
  93. </Layout.HeaderNavTabs>
  94. </TabLayoutHeader>
  95. </React.Fragment>
  96. );
  97. };
  98. export default AlertHeader;
  99. const BorderlessHeader = styled(Layout.Header)`
  100. border-bottom: 0;
  101. /* Not enough buttons to change direction for tablet view */
  102. grid-template-columns: 1fr auto;
  103. `;
  104. const StyledLayoutHeaderContent = styled(Layout.HeaderContent)`
  105. margin-bottom: 0;
  106. margin-right: ${space(2)};
  107. `;
  108. const StyledLayoutTitle = styled(Layout.Title)`
  109. margin-top: ${space(0.5)};
  110. `;
  111. const TabLayoutHeader = styled(Layout.Header)`
  112. padding-top: ${space(1)};
  113. @media (max-width: ${p => p.theme.breakpoints[1]}) {
  114. padding-top: ${space(1)};
  115. }
  116. `;
  117. const Actions = styled(ButtonBar)`
  118. height: 32px;
  119. `;