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

     1  import React, { useState } from 'react';
     2  
     3  import { useAppDispatch, useAppSelector } from '@webapp/redux/hooks';
     4  import {
     5    setDateRange,
     6    selectContinuousState,
     7    actions,
     8  } from '@webapp/redux/reducers/continuous';
     9  import cx from 'classnames';
    10  import Button from '@webapp/ui/Button';
    11  import { readableRange } from '@webapp/util/formatDate';
    12  import { faClock } from '@fortawesome/free-solid-svg-icons/faClock';
    13  import OutsideClickHandler from 'react-outside-click-handler';
    14  import useTimeZone from '@webapp/hooks/timeZone.hook';
    15  import CustomDatePicker from './CustomDatePicker';
    16  import CheckIcon from './CheckIcon';
    17  
    18  const defaultPresets = [
    19    [
    20      { label: 'Last 5 minutes', from: 'now-5m', until: 'now' },
    21      { label: 'Last 15 minutes', from: 'now-15m', until: 'now' },
    22      { label: 'Last 30 minutes', from: 'now-30m', until: 'now' },
    23      { label: 'Last 1 hour', from: 'now-1h', until: 'now' },
    24      { label: 'Last 3 hours', from: 'now-3h', until: 'now' },
    25      { label: 'Last 6 hours', from: 'now-6h', until: 'now' },
    26      { label: 'Last 12 hours', from: 'now-12h', until: 'now' },
    27      { label: 'Last 24 hours', from: 'now-24h', until: 'now' },
    28    ],
    29    [
    30      { label: 'Last 2 days', from: 'now-2d', until: 'now' },
    31      { label: 'Last 7 days', from: 'now-7d', until: 'now' },
    32      { label: 'Last 30 days', from: 'now-30d', until: 'now' },
    33      { label: 'Last 90 days', from: 'now-90d', until: 'now' },
    34    ],
    35  ];
    36  
    37  function findPreset(from: string, until = 'now') {
    38    return defaultPresets
    39      .flat()
    40      .filter((a) => a.until === until)
    41      .find((a) => from === a.from);
    42  }
    43  
    44  function dateToLabel(from: string, until: string, offsetInMinutes: number) {
    45    const preset = findPreset(from, until);
    46  
    47    if (preset) {
    48      return preset.label;
    49    }
    50  
    51    return readableRange(from, until, offsetInMinutes);
    52  }
    53  
    54  function DateRangePicker() {
    55    const dispatch = useAppDispatch();
    56    const { offset } = useTimeZone();
    57    const {
    58      from,
    59      until,
    60      comparisonView: { comparisonMode },
    61    } = useAppSelector(selectContinuousState);
    62    const [opened, setOpened] = useState(false);
    63  
    64    const toggleDropdown = () => {
    65      setOpened(!opened);
    66    };
    67  
    68    const hideDropdown = () => {
    69      setOpened(false);
    70    };
    71    const selectPreset = ({ from, until }: { from: string; until: string }) => {
    72      dispatch(setDateRange({ from, until }));
    73      setOpened(false);
    74  
    75      if (comparisonMode.active) {
    76        dispatch(
    77          actions.setComparisonMode({
    78            ...comparisonMode,
    79            active: false,
    80          })
    81        );
    82      }
    83    };
    84  
    85    const isPresetSelected = (preset: typeof defaultPresets[0][0]) => {
    86      return preset.label === dateToLabel(from, until, offset);
    87    };
    88  
    89    const handleChangeDataRange = (from: string, until: string) => {
    90      dispatch(setDateRange({ from, until }));
    91  
    92      if (comparisonMode.active) {
    93        dispatch(
    94          actions.setComparisonMode({
    95            ...comparisonMode,
    96            active: false,
    97          })
    98        );
    99      }
   100    };
   101  
   102    return (
   103      <div className={opened ? 'drp-container opened' : 'drp-container'}>
   104        <OutsideClickHandler onOutsideClick={hideDropdown}>
   105          <Button
   106            data-testid="time-dropdown-button"
   107            icon={faClock}
   108            onClick={toggleDropdown}
   109          >
   110            {dateToLabel(from, until, offset)}
   111          </Button>
   112          <div className="drp-dropdown">
   113            <div className="drp-quick-presets">
   114              <h4>Quick Presets</h4>
   115              <div className="drp-presets">
   116                {defaultPresets.map((arr, i) => (
   117                  <div key={`preset-${i + 1}`} className="drp-preset-column">
   118                    {arr.map((x) => (
   119                      <button
   120                        type="button"
   121                        className={cx(
   122                          'drp-preset',
   123                          isPresetSelected(x) && 'active'
   124                        )}
   125                        key={x.label}
   126                        onClick={() => selectPreset(x)}
   127                      >
   128                        {x.label}
   129                        {isPresetSelected(x) ? <CheckIcon /> : false}
   130                      </button>
   131                    ))}
   132                  </div>
   133                ))}
   134              </div>
   135            </div>
   136            <CustomDatePicker
   137              from={from}
   138              until={until}
   139              onSubmit={handleChangeDataRange}
   140            />
   141          </div>
   142        </OutsideClickHandler>
   143      </div>
   144    );
   145  }
   146  
   147  export default DateRangePicker;