utils.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import {DurationDisplay} from 'app/components/waterfallTree/types';
  2. import CHART_PALETTE from 'app/constants/chartPalette';
  3. import space from 'app/styles/space';
  4. import {Theme} from 'app/utils/theme';
  5. export const getBackgroundColor = ({
  6. showStriping,
  7. showDetail,
  8. theme,
  9. }: {
  10. showStriping?: boolean;
  11. showDetail?: boolean;
  12. theme: Theme;
  13. }) => {
  14. if (showDetail) {
  15. return theme.textColor;
  16. }
  17. if (showStriping) {
  18. return theme.backgroundSecondary;
  19. }
  20. return theme.background;
  21. };
  22. type HatchProps = {
  23. spanBarHatch: boolean;
  24. };
  25. export function getHatchPattern(
  26. {spanBarHatch}: HatchProps,
  27. primary: string,
  28. alternate: string
  29. ) {
  30. if (spanBarHatch === true) {
  31. return `
  32. background-image: linear-gradient(135deg,
  33. ${alternate},
  34. ${alternate} 2.5px,
  35. ${primary} 2.5px,
  36. ${primary} 5px,
  37. ${alternate} 6px,
  38. ${alternate} 8px,
  39. ${primary} 8px,
  40. ${primary} 11px,
  41. ${alternate} 11px,
  42. ${alternate} 14px,
  43. ${primary} 14px,
  44. ${primary} 16.5px,
  45. ${alternate} 16.5px,
  46. ${alternate} 19px,
  47. ${primary} 20px
  48. );
  49. background-size: 16px 16px;
  50. `;
  51. }
  52. return null;
  53. }
  54. export const getDurationPillAlignment = ({
  55. durationDisplay,
  56. theme,
  57. spanBarHatch,
  58. }: {
  59. durationDisplay: DurationDisplay;
  60. theme: Theme;
  61. spanBarHatch: boolean;
  62. }) => {
  63. switch (durationDisplay) {
  64. case 'left':
  65. return `right: calc(100% + ${space(0.5)});`;
  66. case 'right':
  67. return `left: calc(100% + ${space(0.75)});`;
  68. default:
  69. return `
  70. right: ${space(0.75)};
  71. color: ${spanBarHatch === true ? theme.gray300 : theme.white};
  72. `;
  73. }
  74. };
  75. export const getToggleTheme = ({
  76. isExpanded,
  77. theme,
  78. disabled,
  79. }: {
  80. isExpanded: boolean;
  81. theme: Theme;
  82. disabled: boolean;
  83. }) => {
  84. const buttonTheme = isExpanded ? theme.button.default : theme.button.primary;
  85. if (disabled) {
  86. return `
  87. background: ${buttonTheme.background};
  88. border: 1px solid ${theme.border};
  89. color: ${buttonTheme.color};
  90. cursor: default;
  91. `;
  92. }
  93. return `
  94. background: ${buttonTheme.background};
  95. border: 1px solid ${theme.border};
  96. color: ${buttonTheme.color};
  97. `;
  98. };
  99. export const getDurationDisplay = ({
  100. width,
  101. left,
  102. }: {
  103. width: undefined | number;
  104. left: undefined | number;
  105. }): DurationDisplay => {
  106. const spaceNeeded = 0.3;
  107. if (left === undefined || width === undefined) {
  108. return 'inset';
  109. }
  110. if (left + width < 1 - spaceNeeded) {
  111. return 'right';
  112. }
  113. if (left > spaceNeeded) {
  114. return 'left';
  115. }
  116. return 'inset';
  117. };
  118. export const getHumanDuration = (duration: number): string => {
  119. // note: duration is assumed to be in seconds
  120. const durationMS = duration * 1000;
  121. return `${durationMS.toLocaleString(undefined, {
  122. minimumFractionDigits: 2,
  123. maximumFractionDigits: 2,
  124. })}ms`;
  125. };
  126. export const toPercent = (value: number) => `${(value * 100).toFixed(3)}%`;
  127. type Rect = {
  128. // x and y are left/top coords respectively
  129. x: number;
  130. y: number;
  131. width: number;
  132. height: number;
  133. };
  134. // get position of element relative to top/left of document
  135. const getOffsetOfElement = (element: Element) => {
  136. // left and top are relative to viewport
  137. const {left, top} = element.getBoundingClientRect();
  138. // get values that the document is currently scrolled by
  139. const scrollLeft = window.pageXOffset;
  140. const scrollTop = window.pageYOffset;
  141. return {x: left + scrollLeft, y: top + scrollTop};
  142. };
  143. export const rectOfContent = (element: Element): Rect => {
  144. const {x, y} = getOffsetOfElement(element);
  145. // offsets for the border and any scrollbars (clientLeft and clientTop),
  146. // and if the element was scrolled (scrollLeft and scrollTop)
  147. //
  148. // NOTE: clientLeft and clientTop does not account for any margins nor padding
  149. const contentOffsetLeft = element.clientLeft - element.scrollLeft;
  150. const contentOffsetTop = element.clientTop - element.scrollTop;
  151. return {
  152. x: x + contentOffsetLeft,
  153. y: y + contentOffsetTop,
  154. width: element.scrollWidth,
  155. height: element.scrollHeight,
  156. };
  157. };
  158. export const clamp = (value: number, min: number, max: number): number => {
  159. if (value < min) {
  160. return min;
  161. }
  162. if (value > max) {
  163. return max;
  164. }
  165. return value;
  166. };
  167. const getLetterIndex = (letter: string): number => {
  168. const index = 'abcdefghijklmnopqrstuvwxyz'.indexOf(letter) || 0;
  169. return index === -1 ? 0 : index;
  170. };
  171. const colorsAsArray = Object.keys(CHART_PALETTE).map(key => CHART_PALETTE[17][key]);
  172. export const barColors = {
  173. default: CHART_PALETTE[17][4],
  174. transaction: CHART_PALETTE[17][8],
  175. http: CHART_PALETTE[17][10],
  176. db: CHART_PALETTE[17][17],
  177. };
  178. export const pickBarColour = (input: string | undefined): string => {
  179. // We pick the color for span bars using the first three letters of the op name.
  180. // That way colors stay consistent between transactions.
  181. if (!input || input.length < 3) {
  182. return CHART_PALETTE[17][4];
  183. }
  184. if (barColors[input]) {
  185. return barColors[input];
  186. }
  187. const letterIndex1 = getLetterIndex(input.slice(0, 1));
  188. const letterIndex2 = getLetterIndex(input.slice(1, 2));
  189. const letterIndex3 = getLetterIndex(input.slice(2, 3));
  190. return colorsAsArray[
  191. (letterIndex1 + letterIndex2 + letterIndex3) % colorsAsArray.length
  192. ];
  193. };