LogsNavigationPages.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { css, cx } from '@emotion/css';
  2. import React from 'react';
  3. import { dateTimeFormat, systemDateFormats, TimeZone, AbsoluteTimeRange, GrafanaTheme2 } from '@grafana/data';
  4. import { reportInteraction } from '@grafana/runtime';
  5. import { CustomScrollbar, Spinner, useTheme2 } from '@grafana/ui';
  6. import { LogsPage } from './LogsNavigation';
  7. type Props = {
  8. pages: LogsPage[];
  9. currentPageIndex: number;
  10. oldestLogsFirst: boolean;
  11. timeZone: TimeZone;
  12. loading: boolean;
  13. changeTime: (range: AbsoluteTimeRange) => void;
  14. };
  15. export function LogsNavigationPages({
  16. pages,
  17. currentPageIndex,
  18. oldestLogsFirst,
  19. timeZone,
  20. loading,
  21. changeTime,
  22. }: Props) {
  23. const formatTime = (time: number) => {
  24. return `${dateTimeFormat(time, {
  25. format: systemDateFormats.interval.second,
  26. timeZone: timeZone,
  27. })}`;
  28. };
  29. const createPageContent = (page: LogsPage, index: number) => {
  30. if (currentPageIndex === index && loading) {
  31. return <Spinner />;
  32. }
  33. const topContent = formatTime(oldestLogsFirst ? page.logsRange.from : page.logsRange.to);
  34. const bottomContent = formatTime(oldestLogsFirst ? page.logsRange.to : page.logsRange.from);
  35. return `${topContent} — ${bottomContent}`;
  36. };
  37. const theme = useTheme2();
  38. const styles = getStyles(theme, loading);
  39. return (
  40. <CustomScrollbar autoHide>
  41. <div className={styles.pagesWrapper} data-testid="logsNavigationPages">
  42. <div className={styles.pagesContainer}>
  43. {pages.map((page: LogsPage, index: number) => (
  44. <div
  45. data-testid={`page${index + 1}`}
  46. className={styles.page}
  47. key={page.queryRange.to}
  48. onClick={() => {
  49. reportInteraction('grafana_explore_logs_pagination_clicked', {
  50. pageType: 'page',
  51. pageNumber: index + 1,
  52. });
  53. !loading && changeTime({ from: page.queryRange.from, to: page.queryRange.to });
  54. }}
  55. >
  56. <div className={cx(styles.line, { selectedBg: currentPageIndex === index })} />
  57. <div className={cx(styles.time, { selectedText: currentPageIndex === index })}>
  58. {createPageContent(page, index)}
  59. </div>
  60. </div>
  61. ))}
  62. </div>
  63. </div>
  64. </CustomScrollbar>
  65. );
  66. }
  67. const getStyles = (theme: GrafanaTheme2, loading: boolean) => {
  68. return {
  69. pagesWrapper: css`
  70. height: 100%;
  71. padding-left: ${theme.spacing(0.5)};
  72. display: flex;
  73. flex-direction: column;
  74. overflow-y: scroll;
  75. &::after {
  76. content: '';
  77. display: block;
  78. background: repeating-linear-gradient(
  79. 135deg,
  80. ${theme.colors.background.primary},
  81. ${theme.colors.background.primary} 5px,
  82. ${theme.colors.background.secondary} 5px,
  83. ${theme.colors.background.secondary} 15px
  84. );
  85. width: 3px;
  86. height: inherit;
  87. margin-bottom: 8px;
  88. }
  89. `,
  90. pagesContainer: css`
  91. display: flex;
  92. padding: 0;
  93. flex-direction: column;
  94. `,
  95. page: css`
  96. display: flex;
  97. margin: ${theme.spacing(2)} 0;
  98. cursor: ${loading ? 'auto' : 'pointer'};
  99. white-space: normal;
  100. .selectedBg {
  101. background: ${theme.colors.primary.main};
  102. }
  103. .selectedText {
  104. color: ${theme.colors.primary.main};
  105. }
  106. `,
  107. line: css`
  108. width: 3px;
  109. height: 100%;
  110. align-items: center;
  111. background: ${theme.colors.text.secondary};
  112. `,
  113. time: css`
  114. width: 60px;
  115. min-height: 80px;
  116. font-size: ${theme.v1.typography.size.sm};
  117. padding-left: ${theme.spacing(0.5)};
  118. display: flex;
  119. align-items: center;
  120. `,
  121. };
  122. };