import React, { useContext, useRef, useState, useLayoutEffect } from 'react'; import { ThemeContext, List, GrafanaTheme, selectThemeVariant, ClickOutsideWrapper, CustomScrollbar, DataQueryError, LogRowModel, } from '@grafana/ui'; import { css, cx } from 'emotion'; import { LogRowContextRows, HasMoreContextRows, LogRowContextQueryErrors } from './LogRowContextProvider'; import { Alert } from './Error'; interface LogRowContextProps { row: LogRowModel; context: LogRowContextRows; errors?: LogRowContextQueryErrors; hasMoreContextRows: HasMoreContextRows; onOutsideClick: () => void; onLoadMoreContext: () => void; } const getLogRowContextStyles = (theme: GrafanaTheme) => { const gradientTop = selectThemeVariant( { light: theme.colors.white, dark: theme.colors.dark1, }, theme.type ); const gradientBottom = selectThemeVariant( { light: theme.colors.gray7, dark: theme.colors.dark2, }, theme.type ); const boxShadowColor = selectThemeVariant( { light: theme.colors.gray5, dark: theme.colors.black, }, theme.type ); const borderColor = selectThemeVariant( { light: theme.colors.gray5, dark: theme.colors.dark9, }, theme.type ); return { commonStyles: css` position: absolute; width: calc(100% + 20px); left: -10px; height: 250px; z-index: 2; overflow: hidden; background: ${theme.colors.pageBg}; background: linear-gradient(180deg, ${gradientTop} 0%, ${gradientBottom} 104.25%); box-shadow: 0px 2px 4px ${boxShadowColor}, 0px 0px 2px ${boxShadowColor}; border: 1px solid ${borderColor}; border-radius: ${theme.border.radius.md}; `, header: css` height: 30px; padding: 0 10px; display: flex; align-items: center; background: ${borderColor}; `, logs: css` height: 220px; padding: 10px; `, }; }; interface LogRowContextGroupHeaderProps { row: LogRowModel; rows: Array; onLoadMoreContext: () => void; shouldScrollToBottom?: boolean; canLoadMoreRows?: boolean; } interface LogRowContextGroupProps extends LogRowContextGroupHeaderProps { rows: Array; className: string; error?: string; } const LogRowContextGroupHeader: React.FunctionComponent = ({ row, rows, onLoadMoreContext, canLoadMoreRows, }) => { const theme = useContext(ThemeContext); const { header } = getLogRowContextStyles(theme); return (
Found {rows.length} rows. {(rows.length >= 10 || (rows.length > 10 && rows.length % 10 !== 0)) && canLoadMoreRows && ( onLoadMoreContext()} > Load 10 more )}
); }; const LogRowContextGroup: React.FunctionComponent = ({ row, rows, error, className, shouldScrollToBottom, canLoadMoreRows, onLoadMoreContext, }) => { const theme = useContext(ThemeContext); const { commonStyles, logs } = getLogRowContextStyles(theme); const [scrollTop, setScrollTop] = useState(0); const listContainerRef = useRef(); useLayoutEffect(() => { if (shouldScrollToBottom && listContainerRef.current) { setScrollTop(listContainerRef.current.offsetHeight); } }); const headerProps = { row, rows, onLoadMoreContext, canLoadMoreRows, }; return (
{/* When displaying "after" context */} {shouldScrollToBottom && !error && }
{!error && ( { return (
{item}
); }} /> )} {error && }
{/* When displaying "before" context */} {!shouldScrollToBottom && !error && }
); }; export const LogRowContext: React.FunctionComponent = ({ row, context, errors, onOutsideClick, onLoadMoreContext, hasMoreContextRows, }) => { return (
{context.after && ( )} {context.before && ( )}
); };