monitorHeader.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import styled from '@emotion/styled';
  2. import Breadcrumbs from 'sentry/components/breadcrumbs';
  3. import {SectionHeading} from 'sentry/components/charts/styles';
  4. import Clipboard from 'sentry/components/clipboard';
  5. import IdBadge from 'sentry/components/idBadge';
  6. import * as Layout from 'sentry/components/layouts/thirds';
  7. import TimeSince from 'sentry/components/timeSince';
  8. import {IconCopy} from 'sentry/icons';
  9. import {t} from 'sentry/locale';
  10. import {space} from 'sentry/styles/space';
  11. import {MonitorStatus} from '../types';
  12. import MonitorHeaderActions from './monitorHeaderActions';
  13. import MonitorIcon from './monitorIcon';
  14. type Props = React.ComponentProps<typeof MonitorHeaderActions>;
  15. const statusToLabel: Record<MonitorStatus, string> = {
  16. ok: t('Ok'),
  17. error: t('Failed'),
  18. disabled: t('Disabled'),
  19. active: t('Active'),
  20. missed_checkin: t('Missed'),
  21. };
  22. const MonitorHeader = ({monitor, orgId, onUpdate}: Props) => {
  23. const crumbs = [
  24. {
  25. label: t('Crons'),
  26. to: `/organizations/${orgId}/crons/`,
  27. },
  28. {
  29. label: t('Cron Monitor Details'),
  30. },
  31. ];
  32. return (
  33. <Layout.Header>
  34. <Layout.HeaderContent>
  35. <Breadcrumbs crumbs={crumbs} />
  36. <Layout.Title>
  37. <IdBadge
  38. project={monitor.project}
  39. avatarSize={28}
  40. hideName
  41. avatarProps={{hasTooltip: true, tooltip: monitor.project.slug}}
  42. />
  43. {monitor.name}
  44. </Layout.Title>
  45. <Clipboard value={monitor.slug}>
  46. <MonitorSlug>
  47. {monitor.slug} <IconCopy size="xs" />
  48. </MonitorSlug>
  49. </Clipboard>
  50. </Layout.HeaderContent>
  51. <Layout.HeaderActions>
  52. <MonitorHeaderActions orgId={orgId} monitor={monitor} onUpdate={onUpdate} />
  53. <MonitorStats>
  54. <MonitorStatLabel>{t('Last Check-in')}</MonitorStatLabel>
  55. <MonitorStatLabel>{t('Next Check-in')}</MonitorStatLabel>
  56. <MonitorStatLabel>{t('Status')}</MonitorStatLabel>
  57. <div>{monitor.lastCheckIn && <TimeSince date={monitor.lastCheckIn} />}</div>
  58. <div>{monitor.nextCheckIn && <TimeSince date={monitor.nextCheckIn} />}</div>
  59. <Status>
  60. <MonitorIcon status={monitor.status} size={16} />
  61. <MonitorStatusLabel>{statusToLabel[monitor.status]}</MonitorStatusLabel>
  62. </Status>
  63. </MonitorStats>
  64. </Layout.HeaderActions>
  65. </Layout.Header>
  66. );
  67. };
  68. const MonitorSlug = styled('div')`
  69. margin-top: ${space(1)};
  70. color: ${p => p.theme.subText};
  71. cursor: pointer;
  72. width: max-content;
  73. `;
  74. const MonitorStats = styled('div')`
  75. display: grid;
  76. align-self: flex-end;
  77. grid-template-columns: repeat(3, max-content);
  78. grid-column-gap: ${space(4)};
  79. grid-row-gap: ${space(0.5)};
  80. margin-bottom: ${space(2)};
  81. margin-top: ${space(1)};
  82. `;
  83. const MonitorStatLabel = styled(SectionHeading)`
  84. text-transform: uppercase;
  85. font-size: ${p => p.theme.fontSizeSmall};
  86. text-align: center;
  87. `;
  88. const Status = styled('div')`
  89. display: flex;
  90. align-items: center;
  91. `;
  92. const MonitorStatusLabel = styled('div')`
  93. margin-left: ${space(1)};
  94. `;
  95. export default MonitorHeader;