teamResolutionTime.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import styled from '@emotion/styled';
  2. import {BarChart} from 'sentry/components/charts/barChart';
  3. import type {DateTimeObject} from 'sentry/components/charts/utils';
  4. import LoadingError from 'sentry/components/loadingError';
  5. import LoadingIndicator from 'sentry/components/loadingIndicator';
  6. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  7. import {t} from 'sentry/locale';
  8. import {space} from 'sentry/styles/space';
  9. import type {Organization} from 'sentry/types/organization';
  10. import getDuration from 'sentry/utils/duration/getDuration';
  11. import {useApiQuery} from 'sentry/utils/queryClient';
  12. import {barAxisLabel, sortSeriesByDay} from './utils';
  13. export type TimeToResolution = Record<string, {avg: number; count: number}>;
  14. interface TeamResolutionTimeProps extends DateTimeObject {
  15. organization: Organization;
  16. teamSlug: string;
  17. environment?: string;
  18. }
  19. function TeamResolutionTime({
  20. organization,
  21. teamSlug,
  22. environment,
  23. start,
  24. end,
  25. period,
  26. utc,
  27. }: TeamResolutionTimeProps) {
  28. const datetime = {start, end, period, utc};
  29. const {
  30. data: resolutionTime,
  31. isPending,
  32. isError,
  33. refetch,
  34. } = useApiQuery<TimeToResolution>(
  35. [
  36. `/teams/${organization.slug}/${teamSlug}/time-to-resolution/`,
  37. {
  38. query: {
  39. ...normalizeDateTimeParams(datetime),
  40. environment,
  41. },
  42. },
  43. ],
  44. {staleTime: 5000}
  45. );
  46. if (isPending) {
  47. return (
  48. <ChartWrapper>
  49. <LoadingIndicator />
  50. </ChartWrapper>
  51. );
  52. }
  53. if (isError) {
  54. return <LoadingError onRetry={refetch} />;
  55. }
  56. const data = Object.entries(resolutionTime ?? {}).map(([bucket, {avg}]) => ({
  57. value: avg,
  58. name: new Date(bucket).getTime(),
  59. }));
  60. const seriesData = sortSeriesByDay(data);
  61. return (
  62. <ChartWrapper>
  63. <BarChart
  64. style={{height: 190}}
  65. isGroupedByDate
  66. useShortDate
  67. period="7d"
  68. tooltip={{
  69. valueFormatter: (value: number) => getDuration(value, 1),
  70. }}
  71. yAxis={{
  72. // Each yAxis marker will increase by 1 day
  73. minInterval: 86400,
  74. axisLabel: {
  75. formatter: (value: number) => {
  76. if (value === 0) {
  77. return '';
  78. }
  79. return getDuration(value, 0, true, true);
  80. },
  81. },
  82. }}
  83. legend={{right: 0, top: 0}}
  84. xAxis={barAxisLabel()}
  85. series={[
  86. {
  87. seriesName: t('Time to Resolution'),
  88. data: seriesData,
  89. silent: true,
  90. barCategoryGap: '5%',
  91. },
  92. ]}
  93. />
  94. </ChartWrapper>
  95. );
  96. }
  97. export default TeamResolutionTime;
  98. const ChartWrapper = styled('div')`
  99. padding: ${space(2)} ${space(2)} 0 ${space(2)};
  100. `;