sampleImages.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import styled from '@emotion/styled';
  2. import {t} from 'sentry/locale';
  3. import {formatBytesBase2} from 'sentry/utils';
  4. import getDynamicText from 'sentry/utils/getDynamicText';
  5. import {useIndexedResourcesQuery} from 'sentry/views/performance/browser/resources/utils/useIndexedResourceQuery';
  6. import ChartPanel from 'sentry/views/starfish/components/chartPanel';
  7. import {SpanIndexedField} from 'sentry/views/starfish/types';
  8. type Props = {groupId: string};
  9. const {SPAN_GROUP, SPAN_DESCRIPTION, HTTP_RESPONSE_CONTENT_LENGTH} = SpanIndexedField;
  10. const imageWidth = '200px';
  11. function SampleImages({groupId}: Props) {
  12. const imageResources = useIndexedResourcesQuery({
  13. queryConditions: [`${SPAN_GROUP}:${groupId}`],
  14. sorts: [{field: `measurements.${HTTP_RESPONSE_CONTENT_LENGTH}`, kind: 'desc'}],
  15. limit: 100,
  16. });
  17. const uniqueResources = new Set();
  18. const filteredResources = imageResources.data
  19. .filter(resource => {
  20. const fileName = getFileNameFromDescription(resource[SPAN_DESCRIPTION]);
  21. if (uniqueResources.has(fileName)) {
  22. return false;
  23. }
  24. uniqueResources.add(fileName);
  25. return true;
  26. })
  27. .splice(0, 5);
  28. return (
  29. <ChartPanel title={t('Example Images')}>
  30. <ImageWrapper>
  31. {filteredResources.map(resource => {
  32. return (
  33. <ImageContainer
  34. src={resource[SPAN_DESCRIPTION]}
  35. fileName={getFileNameFromDescription(resource[SPAN_DESCRIPTION])}
  36. size={resource[`measurements.${HTTP_RESPONSE_CONTENT_LENGTH}`]}
  37. key={resource[SPAN_DESCRIPTION]}
  38. />
  39. );
  40. })}
  41. </ImageWrapper>
  42. </ChartPanel>
  43. );
  44. }
  45. function ImageContainer({
  46. src,
  47. fileName,
  48. size,
  49. }: {
  50. fileName: string;
  51. size: number;
  52. src: string;
  53. }) {
  54. const fileSize = getDynamicText({
  55. value: formatBytesBase2(size),
  56. fixed: 'xx KB',
  57. });
  58. return (
  59. <div style={{width: '100%', wordWrap: 'break-word'}}>
  60. <img src={src} style={{minWidth: imageWidth, height: '200px'}} />
  61. {fileName} ({fileSize})
  62. </div>
  63. );
  64. }
  65. const ImageWrapper = styled('div')`
  66. display: grid;
  67. grid-template-columns: repeat(auto-fill, ${imageWidth});
  68. gap: 30px;
  69. `;
  70. const getFileNameFromDescription = (description: string) => {
  71. try {
  72. const url = new URL(description);
  73. return url.pathname.split('/').pop() || '';
  74. } catch (e) {
  75. return description;
  76. }
  77. };
  78. export default SampleImages;