github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/components/TimelineChart/AnnotationMark/index.tsx (about)

     1  /* eslint-disable default-case, consistent-return */
     2  import Color from 'color';
     3  import React, { useState } from 'react';
     4  import classNames from 'classnames/bind';
     5  import AnnotationInfo from '@webapp/pages/continuous/contextMenu/AnnotationInfo';
     6  import useTimeZone from '@webapp/hooks/timeZone.hook';
     7  
     8  import styles from './styles.module.scss';
     9  
    10  const cx = classNames.bind(styles);
    11  
    12  interface IAnnotationMarkProps {
    13    type: 'message';
    14    color: Color;
    15    value: {
    16      content: string;
    17      timestamp: number;
    18    };
    19    posX: number;
    20  }
    21  
    22  const getIcon = (type: IAnnotationMarkProps['type']) => {
    23    switch (type) {
    24      case 'message':
    25        return styles.message;
    26    }
    27  };
    28  
    29  const AnnotationMark = ({ type, color, value, posX }: IAnnotationMarkProps) => {
    30    const { offset } = useTimeZone();
    31    const [visible, setVisible] = useState(false);
    32    const [target, setTarget] = useState<Element>();
    33    const [hovered, setHovered] = useState(false);
    34  
    35    const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    36      e.stopPropagation();
    37      setTarget(e.target as Element);
    38      setVisible(true);
    39    };
    40  
    41    // TODO: 150 refers to the timeline height, clean this up
    42    const pos = { x: posX, y: 150 };
    43    const annotationInfoPopover = target ? (
    44      <AnnotationInfo
    45        popoverAnchorPoint={pos}
    46        value={value}
    47        timezone={offset === 0 ? 'utc' : 'browser'}
    48        timestamp={value.timestamp}
    49        isOpen={visible}
    50        onClose={() => setVisible(false)}
    51        popoverClassname={styles.form}
    52      />
    53    ) : null;
    54  
    55    const onHoverStyle = {
    56      backgroundColor: hovered ? color.darken(0.2).hex() : color.hex(),
    57      zIndex: hovered ? 2 : 1,
    58    };
    59  
    60    return (
    61      <>
    62        <div
    63          data-testid="annotation_mark_wrapper"
    64          onClick={onClick}
    65          style={onHoverStyle}
    66          className={cx(styles.wrapper, getIcon(type))}
    67          role="none"
    68          onMouseEnter={() => setHovered(true)}
    69          onMouseLeave={() => setHovered(false)}
    70        />
    71        {annotationInfoPopover}
    72      </>
    73    );
    74  };
    75  
    76  export default AnnotationMark;