userMisery.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import * as React from 'react';
  2. import ScoreBar from 'app/components/scoreBar';
  3. import Tooltip from 'app/components/tooltip';
  4. import CHART_PALETTE from 'app/constants/chartPalette';
  5. import {tct} from 'app/locale';
  6. import {defined} from 'app/utils';
  7. type Props = {
  8. bars: number;
  9. barHeight: number;
  10. userMisery: number;
  11. miseryLimit: number | undefined;
  12. totalUsers: number | undefined;
  13. miserableUsers: number | undefined;
  14. };
  15. function UserMisery(props: Props) {
  16. const {bars, barHeight, userMisery, miseryLimit, totalUsers, miserableUsers} = props;
  17. // User Misery will always be > 0 because of the maximum a posteriori estimate
  18. // and below 5% will always be an overestimation of the actual proportion
  19. // of miserable to total unique users. We are going to visualize it as
  20. // 0 User Misery while still preserving the actual value for sorting purposes.
  21. const adjustedMisery = userMisery > 0.05 ? userMisery : 0;
  22. const palette = new Array(bars).fill([CHART_PALETTE[0][0]]);
  23. const score = Math.round(adjustedMisery * palette.length);
  24. let title: React.ReactNode;
  25. if (defined(miserableUsers) && defined(totalUsers) && defined(miseryLimit)) {
  26. title = tct(
  27. '[miserableUsers] out of [totalUsers] unique users waited more than [duration]ms',
  28. {
  29. miserableUsers,
  30. totalUsers,
  31. duration: 4 * miseryLimit,
  32. }
  33. );
  34. } else if (defined(miseryLimit)) {
  35. title = tct(
  36. 'User Misery score is [userMisery], representing users who waited more than more than [duration]ms.',
  37. {
  38. duration: 4 * miseryLimit,
  39. userMisery: userMisery.toFixed(3),
  40. }
  41. );
  42. } else {
  43. title = tct('User Misery score is [userMisery].', {
  44. userMisery: userMisery.toFixed(3),
  45. });
  46. }
  47. return (
  48. <Tooltip title={title} containerDisplayMode="block">
  49. <ScoreBar size={barHeight} score={score} palette={palette} radius={0} />
  50. </Tooltip>
  51. );
  52. }
  53. export default UserMisery;