resourceView.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {CompactSelect} from 'sentry/components/compactSelect';
  4. import {t} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import {trackAnalytics} from 'sentry/utils/analytics';
  7. import {useLocation} from 'sentry/utils/useLocation';
  8. import {useNavigate} from 'sentry/utils/useNavigate';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import {getResourceTypeFilter} from 'sentry/views/insights/browser/common/queries/useResourcesQuery';
  11. import RenderBlockingSelector from 'sentry/views/insights/browser/resources/components/renderBlockingSelector';
  12. import ResourceTable from 'sentry/views/insights/browser/resources/components/tables/resourceTable';
  13. import {
  14. FONT_FILE_EXTENSIONS,
  15. IMAGE_FILE_EXTENSIONS,
  16. } from 'sentry/views/insights/browser/resources/constants';
  17. import {DEFAULT_RESOURCE_TYPES} from 'sentry/views/insights/browser/resources/settings';
  18. import {ResourceSpanOps} from 'sentry/views/insights/browser/resources/types';
  19. import {
  20. BrowserStarfishFields,
  21. useResourceModuleFilters,
  22. } from 'sentry/views/insights/browser/resources/utils/useResourceFilters';
  23. import {useResourceSort} from 'sentry/views/insights/browser/resources/utils/useResourceSort';
  24. import {QueryParameterNames} from 'sentry/views/insights/common/views/queryParameters';
  25. import {TransactionSelector} from 'sentry/views/insights/common/views/spans/selectors/transactionSelector';
  26. import type {ModuleFilters} from 'sentry/views/insights/common/views/spans/useModuleFilters';
  27. import {ResourceLandingPageCharts} from './charts/resourceLandingPageCharts';
  28. const {
  29. SPAN_OP: RESOURCE_TYPE,
  30. SPAN_DOMAIN,
  31. TRANSACTION,
  32. RESOURCE_RENDER_BLOCKING_STATUS,
  33. USER_GEO_SUBREGION,
  34. } = BrowserStarfishFields;
  35. type Option = {
  36. label: string | React.ReactElement;
  37. value: string;
  38. };
  39. function ResourceView() {
  40. const filters = useResourceModuleFilters();
  41. const sort = useResourceSort();
  42. const spanTimeChartsFilters: ModuleFilters = {
  43. 'span.op': `[${DEFAULT_RESOURCE_TYPES.join(',')}]`,
  44. ...(filters[SPAN_DOMAIN] ? {[SPAN_DOMAIN]: filters[SPAN_DOMAIN]} : {}),
  45. };
  46. const extraQuery = [
  47. ...getResourceTypeFilter(undefined, DEFAULT_RESOURCE_TYPES),
  48. ...(filters[USER_GEO_SUBREGION]
  49. ? [`user.geo.subregion:[${filters[USER_GEO_SUBREGION].join(',')}]`]
  50. : []),
  51. ];
  52. return (
  53. <Fragment>
  54. <SpanTimeChartsContainer>
  55. <ResourceLandingPageCharts
  56. appliedFilters={spanTimeChartsFilters}
  57. extraQuery={extraQuery}
  58. />
  59. </SpanTimeChartsContainer>
  60. <DropdownContainer>
  61. <ResourceTypeSelector value={filters[RESOURCE_TYPE] || ''} />
  62. <TransactionSelector
  63. value={filters[TRANSACTION] || ''}
  64. defaultResourceTypes={DEFAULT_RESOURCE_TYPES}
  65. />
  66. <RenderBlockingSelector value={filters[RESOURCE_RENDER_BLOCKING_STATUS] || ''} />
  67. </DropdownContainer>
  68. <ResourceTable sort={sort} defaultResourceTypes={DEFAULT_RESOURCE_TYPES} />
  69. </Fragment>
  70. );
  71. }
  72. function ResourceTypeSelector({value}: {value?: string}) {
  73. const navigate = useNavigate();
  74. const location = useLocation();
  75. const organization = useOrganization();
  76. const hasImageView = organization.features.includes('insights-initial-modules');
  77. const options: Option[] = [
  78. {value: '', label: 'All'},
  79. {value: 'resource.script', label: `${t('JavaScript')} (.js)`},
  80. {value: 'resource.css', label: `${t('Stylesheet')} (.css)`},
  81. {
  82. value: 'resource.font',
  83. label: `${t('Font')} (${FONT_FILE_EXTENSIONS.map(e => `.${e}`).join(', ')})`,
  84. },
  85. ...(hasImageView
  86. ? [
  87. {
  88. value: ResourceSpanOps.IMAGE,
  89. label: `${t('Image')} (${IMAGE_FILE_EXTENSIONS.map(e => `.${e}`).join(', ')})`,
  90. },
  91. ]
  92. : []),
  93. ];
  94. return (
  95. <CompactSelect
  96. style={{maxWidth: '200px'}}
  97. triggerProps={{prefix: `${t('Type')}`}}
  98. options={options}
  99. value={value ?? ''}
  100. onChange={newValue => {
  101. trackAnalytics('insight.asset.filter_by_type', {
  102. organization,
  103. filter: newValue?.value,
  104. });
  105. navigate({
  106. ...location,
  107. query: {
  108. ...location.query,
  109. [RESOURCE_TYPE]: newValue?.value,
  110. [QueryParameterNames.SPANS_CURSOR]: undefined,
  111. },
  112. });
  113. }}
  114. />
  115. );
  116. }
  117. export const SpanTimeChartsContainer = styled('div')`
  118. margin-bottom: ${space(2)};
  119. `;
  120. const DropdownContainer = styled('div')`
  121. display: flex;
  122. gap: ${space(2)};
  123. margin-bottom: ${space(2)};
  124. flex-wrap: wrap;
  125. `;
  126. export default ResourceView;