sparkline.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import {Theme} from '@emotion/react';
  2. import {LineChart} from 'echarts/charts';
  3. import * as echarts from 'echarts/core';
  4. import {SVGRenderer} from 'echarts/renderers';
  5. import ReactEChartsCore from 'echarts-for-react/lib/core';
  6. import moment from 'moment';
  7. import MarkLine from 'sentry/components/charts/components/markLine';
  8. import {Series, SeriesDataUnit} from 'sentry/types/echarts';
  9. type SparklineProps = {
  10. series: Series;
  11. color?: string | string[];
  12. markLine?: Series;
  13. width?: number;
  14. };
  15. export default function Sparkline({series, width, color, markLine}: SparklineProps) {
  16. echarts.use([LineChart, SVGRenderer]);
  17. if (!series.data) {
  18. return null;
  19. }
  20. const valueSeries = {
  21. data: series.data.map(datum => datum.value),
  22. type: 'line',
  23. showSymbol: false,
  24. smooth: true,
  25. };
  26. return (
  27. <ReactEChartsCore
  28. echarts={echarts}
  29. option={{
  30. color,
  31. series: [valueSeries, markLine],
  32. xAxis: {
  33. show: false,
  34. data: series.data.map(datum => datum.name),
  35. type: 'category',
  36. },
  37. yAxis: {
  38. show: false,
  39. type: 'value',
  40. },
  41. grid: {
  42. left: 3,
  43. top: 3,
  44. right: 3,
  45. bottom: 3,
  46. },
  47. }}
  48. notMerge
  49. style={{
  50. height: 25,
  51. width: width ?? 200,
  52. }}
  53. lazyUpdate
  54. theme="theme_name"
  55. />
  56. );
  57. }
  58. type MultiSparklineProps = {
  59. color: string[];
  60. series: Series[];
  61. height?: number;
  62. markLine?: Series;
  63. width?: number;
  64. };
  65. export function MultiSparkline({
  66. series,
  67. markLine,
  68. width,
  69. height,
  70. color,
  71. }: MultiSparklineProps) {
  72. echarts.use([LineChart, SVGRenderer]);
  73. function getValueSeries(targetSeries, i) {
  74. return {
  75. data: targetSeries.data.map(datum => datum.value),
  76. type: 'line',
  77. showSymbol: false,
  78. smooth: true,
  79. lineStyle: {color: color[i], width: [1, 2][i]},
  80. yAxisIndex: i,
  81. };
  82. }
  83. return (
  84. <ReactEChartsCore
  85. echarts={echarts}
  86. option={{
  87. series: [...series.map((item, index) => getValueSeries(item, index)), markLine],
  88. xAxis: {
  89. show: false,
  90. data: getValueSeries(series[0], 0).data.map(datum => datum.name),
  91. type: 'category',
  92. },
  93. yAxis: [
  94. {
  95. show: false,
  96. type: 'value',
  97. },
  98. {
  99. show: false,
  100. type: 'value',
  101. },
  102. ],
  103. grid: {
  104. left: 3,
  105. top: 3,
  106. right: 3,
  107. bottom: 3,
  108. },
  109. }}
  110. notMerge
  111. style={{
  112. height: height ?? 25,
  113. width: width ?? 200,
  114. }}
  115. lazyUpdate
  116. theme="theme_name"
  117. />
  118. );
  119. }
  120. export function generateMarkLine(
  121. title: string,
  122. position: string,
  123. data: SeriesDataUnit[],
  124. theme: Theme
  125. ) {
  126. const index = data.findIndex(item => {
  127. return (
  128. Math.abs(moment.duration(moment(item.name).diff(moment(position))).asSeconds()) <
  129. 86400
  130. );
  131. });
  132. return {
  133. seriesName: title,
  134. type: 'line',
  135. color: theme.blue300,
  136. data: [],
  137. xAxisIndex: 0,
  138. yAxisIndex: 0,
  139. markLine: MarkLine({
  140. silent: true,
  141. animation: false,
  142. lineStyle: {color: theme.blue300, type: 'dotted'},
  143. data: [
  144. {
  145. xAxis: index,
  146. },
  147. ],
  148. label: {
  149. show: false,
  150. },
  151. }),
  152. };
  153. }
  154. export function generateHorizontalLine(title: string, position: number, theme: Theme) {
  155. return {
  156. seriesName: title,
  157. type: 'line',
  158. color: theme.blue300,
  159. data: [],
  160. xAxisIndex: 0,
  161. yAxisIndex: 0,
  162. markLine: MarkLine({
  163. silent: true,
  164. animation: false,
  165. lineStyle: {color: theme.blue300, type: 'dotted'},
  166. data: [
  167. {
  168. yAxis: position,
  169. },
  170. ],
  171. label: {
  172. show: true,
  173. position: 'insideStart',
  174. formatter: title,
  175. },
  176. }),
  177. };
  178. }