webVitalsLandingPage.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import {useState} from 'react';
  2. import Breadcrumbs from 'sentry/components/breadcrumbs';
  3. import DatePageFilter from 'sentry/components/datePageFilter';
  4. import FeatureBadge from 'sentry/components/featureBadge';
  5. import * as Layout from 'sentry/components/layouts/thirds';
  6. import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
  7. import ProjectPageFilter from 'sentry/components/projectPageFilter';
  8. import {t} from 'sentry/locale';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import usePageFilters from 'sentry/utils/usePageFilters';
  11. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  12. import WebVitalMeters from 'sentry/views/performance/browser/webVitals/components/webVitalMeters';
  13. import {PagePerformanceTables} from 'sentry/views/performance/browser/webVitals/pagePerformanceTables';
  14. import {PerformanceScoreChart} from 'sentry/views/performance/browser/webVitals/performanceScoreChart';
  15. import {calculatePerformanceScore} from 'sentry/views/performance/browser/webVitals/utils/calculatePerformanceScore';
  16. import {WebVitals} from 'sentry/views/performance/browser/webVitals/utils/types';
  17. import {useProjectWebVitalsQuery} from 'sentry/views/performance/browser/webVitals/utils/useProjectWebVitalsQuery';
  18. import {WebVitalsDetailPanel} from 'sentry/views/performance/browser/webVitals/webVitalsDetailPanel';
  19. import {ModulePageProviders} from 'sentry/views/performance/database/modulePageProviders';
  20. export default function WebVitalsLandingPage() {
  21. const organization = useOrganization();
  22. const pageFilters = usePageFilters();
  23. const [state, setState] = useState<{webVital: WebVitals | null}>({
  24. webVital: null,
  25. });
  26. const {data: projectData} = useProjectWebVitalsQuery({pageFilters});
  27. const projectScore = calculatePerformanceScore({
  28. lcp: projectData?.data[0]['p75(measurements.lcp)'] as number,
  29. fcp: projectData?.data[0]['p75(measurements.fcp)'] as number,
  30. cls: projectData?.data[0]['p75(measurements.cls)'] as number,
  31. ttfb: projectData?.data[0]['p75(measurements.ttfb)'] as number,
  32. fid: projectData?.data[0]['p75(measurements.fid)'] as number,
  33. });
  34. return (
  35. <ModulePageProviders title={[t('Performance'), t('Page Loads')].join(' — ')}>
  36. <Layout.Header>
  37. <Layout.HeaderContent>
  38. <Breadcrumbs
  39. crumbs={[
  40. {
  41. label: 'Performance',
  42. to: normalizeUrl(`/organizations/${organization.slug}/performance/`),
  43. preservePageFilters: true,
  44. },
  45. {
  46. label: 'Page Loads',
  47. },
  48. ]}
  49. />
  50. <Layout.Title>
  51. {t('Page Loads')}
  52. <FeatureBadge type="alpha" />
  53. </Layout.Title>
  54. </Layout.HeaderContent>
  55. </Layout.Header>
  56. <Layout.Body>
  57. <Layout.Main fullWidth>
  58. <PageFilterBar condensed>
  59. <ProjectPageFilter />
  60. <DatePageFilter alignDropdown="left" />
  61. </PageFilterBar>
  62. <PerformanceScoreChart projectScore={projectScore} />
  63. <WebVitalMeters
  64. projectData={projectData}
  65. projectScore={projectScore}
  66. onClick={webVital => setState({...state, webVital})}
  67. />
  68. <PagePerformanceTables />
  69. </Layout.Main>
  70. </Layout.Body>
  71. <WebVitalsDetailPanel
  72. webVital={state.webVital}
  73. onClose={() => {
  74. setState({...state, webVital: null});
  75. }}
  76. />
  77. </ModulePageProviders>
  78. );
  79. }