import { css } from '@emotion/css'; import React, { useEffect, useRef } from 'react'; import { GrafanaTheme2, LogRowModel } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; import { Menu, useStyles2 } from '@grafana/ui'; import { copyText } from '../utils'; interface PopoverMenuProps { selection: string; x: number; y: number; onClickFilterValue?: (value: string, refId?: string) => void; onClickFilterOutValue?: (value: string, refId?: string) => void; row: LogRowModel; close: () => void; } export const PopoverMenu = ({ x, y, onClickFilterValue, onClickFilterOutValue, selection, row, close, }: PopoverMenuProps) => { const containerRef = useRef(null); const styles = useStyles2(getStyles); useEffect(() => { function handleEscape(e: KeyboardEvent) { if (e.key === 'Escape') { close(); } } document.addEventListener('keyup', handleEscape); return () => { document.removeEventListener('keyup', handleEscape); }; }, [close]); const supported = onClickFilterValue || onClickFilterOutValue; if (!supported) { return null; } return (
{ copyText(selection, containerRef); close(); track('copy', selection.length, row.datasourceType); }} /> {onClickFilterValue && ( { onClickFilterValue(selection, row.dataFrame.refId); close(); track('line_contains', selection.length, row.datasourceType); }} /> )} {onClickFilterOutValue && ( { onClickFilterOutValue(selection, row.dataFrame.refId); close(); track('line_does_not_contain', selection.length, row.datasourceType); }} /> )}
); }; function track(action: string, selectionLength: number, dataSourceType: string | undefined) { reportInteraction(`grafana_explore_logs_popover_menu`, { action, selection_length: selectionLength, ds_type: dataSourceType || 'unknown', }); } const getStyles = (theme: GrafanaTheme2) => ({ menu: css({ position: 'absolute', zIndex: theme.zIndex.modal, }), });