statusBreakdown.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import {Fragment} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {Location} from 'history';
  5. import BreakdownBars from 'app/components/charts/breakdownBars';
  6. import ErrorPanel from 'app/components/charts/errorPanel';
  7. import {SectionHeading} from 'app/components/charts/styles';
  8. import EmptyStateWarning from 'app/components/emptyStateWarning';
  9. import Placeholder from 'app/components/placeholder';
  10. import QuestionTooltip from 'app/components/questionTooltip';
  11. import {IconWarning} from 'app/icons';
  12. import {t} from 'app/locale';
  13. import {LightWeightOrganization} from 'app/types';
  14. import DiscoverQuery from 'app/utils/discover/discoverQuery';
  15. import EventView from 'app/utils/discover/eventView';
  16. import {stringifyQueryObject, tokenizeSearch} from 'app/utils/tokenizeSearch';
  17. import {getTermHelp, PERFORMANCE_TERM} from 'app/views/performance/data';
  18. type Props = {
  19. organization: LightWeightOrganization;
  20. location: Location;
  21. eventView: EventView;
  22. };
  23. function StatusBreakdown({eventView, location, organization}: Props) {
  24. const breakdownView = eventView
  25. .withColumns([
  26. {kind: 'function', function: ['count', '', '']},
  27. {kind: 'field', field: 'transaction.status'},
  28. ])
  29. .withSorts([{kind: 'desc', field: 'count'}]);
  30. return (
  31. <Fragment>
  32. <SectionHeading>
  33. {t('Status Breakdown')}
  34. <QuestionTooltip
  35. position="top"
  36. title={getTermHelp(organization, PERFORMANCE_TERM.STATUS_BREAKDOWN)}
  37. size="sm"
  38. />
  39. </SectionHeading>
  40. <DiscoverQuery
  41. eventView={breakdownView}
  42. location={location}
  43. orgSlug={organization.slug}
  44. referrer="api.performance.status-breakdown"
  45. >
  46. {({isLoading, error, tableData}) => {
  47. if (isLoading) {
  48. return <Placeholder height="124px" />;
  49. }
  50. if (error) {
  51. return (
  52. <ErrorPanel height="124px">
  53. <IconWarning color="gray300" size="lg" />
  54. </ErrorPanel>
  55. );
  56. }
  57. if (!tableData || tableData.data.length === 0) {
  58. return (
  59. <EmptyStatusBreakdown small>{t('No statuses found')}</EmptyStatusBreakdown>
  60. );
  61. }
  62. const points = tableData.data.map(row => ({
  63. label: String(row['transaction.status']),
  64. value: parseInt(String(row.count), 10),
  65. onClick: () => {
  66. const query = tokenizeSearch(eventView.query);
  67. query
  68. .removeTag('!transaction.status')
  69. .setTagValues('transaction.status', [row['transaction.status']]);
  70. browserHistory.push({
  71. pathname: location.pathname,
  72. query: {
  73. ...location.query,
  74. cursor: undefined,
  75. query: stringifyQueryObject(query),
  76. },
  77. });
  78. },
  79. }));
  80. return <BreakdownBars data={points} />;
  81. }}
  82. </DiscoverQuery>
  83. </Fragment>
  84. );
  85. }
  86. const EmptyStatusBreakdown = styled(EmptyStateWarning)`
  87. height: 124px;
  88. padding: 50px 15%;
  89. `;
  90. export default StatusBreakdown;