mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.5][Session view][TTY output] UI Improvements (#141175)
This commit is contained in:
parent
99e367446b
commit
4c0c0db9c5
7 changed files with 113 additions and 67 deletions
|
@ -75,7 +75,7 @@ export const useStyles = (tty?: Teletype, show?: boolean) => {
|
|||
transform: `translateY(${show ? 0 : '100%'})`,
|
||||
transition: 'transform .2s',
|
||||
width: '100%',
|
||||
height: 'calc(100% - 120px)',
|
||||
height: 'calc(100% - 112px)',
|
||||
overflow: 'auto',
|
||||
backgroundColor: colors.ink,
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
EuiFlexItem,
|
||||
EuiButtonIcon,
|
||||
EuiToolTip,
|
||||
EuiButtonIconProps,
|
||||
} from '@elastic/eui';
|
||||
import { findIndex } from 'lodash';
|
||||
import { ProcessStartMarker, ProcessEvent } from '../../../common/types/process_tree';
|
||||
|
@ -54,6 +55,13 @@ export const TTYPlayerControls = ({
|
|||
}: TTYPlayerControlsDeps) => {
|
||||
const styles = useStyles();
|
||||
|
||||
const commonButtonProps: Partial<EuiButtonIconProps> = {
|
||||
display: 'empty',
|
||||
size: 's',
|
||||
color: 'ghost',
|
||||
css: styles.controlButton,
|
||||
};
|
||||
|
||||
const onLineChange = useCallback(
|
||||
(event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>) => {
|
||||
const line = parseInt((event?.target as HTMLInputElement).value || '0', 10);
|
||||
|
@ -111,65 +119,55 @@ export const TTYPlayerControls = ({
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={TTY_START}>
|
||||
<EuiButtonIcon
|
||||
css={styles.controlButton}
|
||||
data-test-subj="sessionView:TTYPlayerControlsStart"
|
||||
iconType="arrowStart"
|
||||
display="empty"
|
||||
size="m"
|
||||
aria-label={TTY_START}
|
||||
onClick={seekToStart}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={TTY_PREVIOUS}>
|
||||
<EuiButtonIcon
|
||||
css={styles.controlButton}
|
||||
data-test-subj="sessionView:TTYPlayerControlsPrevious"
|
||||
iconType="arrowLeft"
|
||||
display="empty"
|
||||
size="m"
|
||||
aria-label={TTY_PREVIOUS}
|
||||
onClick={seekToPrevProcess}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={isPlaying ? TTY_PAUSE : TTY_PLAY}>
|
||||
<EuiButtonIcon
|
||||
css={styles.controlButton}
|
||||
data-test-subj="sessionView:TTYPlayerControlsPlay"
|
||||
iconType={isPlaying ? 'pause' : 'playFilled'}
|
||||
display="empty"
|
||||
size="m"
|
||||
aria-label={isPlaying ? TTY_PAUSE : TTY_PLAY}
|
||||
onClick={onTogglePlayback}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={TTY_NEXT}>
|
||||
<EuiButtonIcon
|
||||
css={styles.controlButton}
|
||||
data-test-subj="sessionView:TTYPlayerControlsNext"
|
||||
iconType="arrowRight"
|
||||
display="empty"
|
||||
size="m"
|
||||
aria-label={TTY_NEXT}
|
||||
onClick={seekToNextProcess}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={TTY_END}>
|
||||
<EuiButtonIcon
|
||||
css={styles.controlButton}
|
||||
data-test-subj="sessionView:TTYPlayerControlsEnd"
|
||||
iconType="arrowEnd"
|
||||
display="empty"
|
||||
size="m"
|
||||
aria-label={TTY_END}
|
||||
onClick={seekToEnd}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
|
@ -179,6 +177,7 @@ export const TTYPlayerControls = ({
|
|||
linesLength={linesLength}
|
||||
currentLine={currentLine}
|
||||
onChange={onLineChange}
|
||||
onSeekLine={onSeekLine}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -188,6 +187,7 @@ export const TTYPlayerControls = ({
|
|||
onClick={handleViewInSession}
|
||||
iconType="arrowRight"
|
||||
aria-label={VIEW_IN_SESSION}
|
||||
color="ghost"
|
||||
>
|
||||
{VIEW_IN_SESSION}
|
||||
</EuiButtonEmpty>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import React, { ChangeEvent, MouseEvent, useMemo } from 'react';
|
||||
import { EuiRange } from '@elastic/eui';
|
||||
import { EuiRange, EuiToolTip } from '@elastic/eui';
|
||||
import type { ProcessStartMarker } from '../../../../common/types/process_tree';
|
||||
import { useStyles } from './styles';
|
||||
import { PlayHead } from './play_head';
|
||||
|
@ -16,11 +16,13 @@ type Props = {
|
|||
linesLength: number;
|
||||
currentLine: number;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>) => void;
|
||||
onSeekLine(line: number): void;
|
||||
};
|
||||
|
||||
type TTYPlayerLineMarker = {
|
||||
line: number;
|
||||
type: 'output' | 'data_limited';
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const TTYPlayerControlsMarkers = ({
|
||||
|
@ -28,8 +30,11 @@ export const TTYPlayerControlsMarkers = ({
|
|||
linesLength,
|
||||
currentLine,
|
||||
onChange,
|
||||
onSeekLine,
|
||||
}: Props) => {
|
||||
const styles = useStyles();
|
||||
const progress = useMemo(() => (currentLine / linesLength) * 100, [currentLine, linesLength]);
|
||||
|
||||
const styles = useStyles(progress);
|
||||
|
||||
const markers = useMemo(() => {
|
||||
if (processStartMarkers.length < 1) {
|
||||
|
@ -41,22 +46,29 @@ export const TTYPlayerControlsMarkers = ({
|
|||
type:
|
||||
event.process?.io?.max_bytes_per_process_exceeded === true ? 'data_limited' : 'output',
|
||||
line,
|
||||
name: event.process?.name,
|
||||
} as TTYPlayerLineMarker)
|
||||
);
|
||||
}, [processStartMarkers]);
|
||||
|
||||
const markersLength = markers.length;
|
||||
|
||||
const currentSelectedType = useMemo(() => {
|
||||
if (!markersLength) {
|
||||
return undefined;
|
||||
}
|
||||
const currentSelected =
|
||||
currentLine >= markers[markersLength - 1].line
|
||||
? markersLength - 1
|
||||
: markers.findIndex((marker) => marker.line > currentLine) - 1;
|
||||
|
||||
return markers[Math.max(0, currentSelected)].type;
|
||||
}, [currentLine, markers, markersLength]);
|
||||
|
||||
if (!markersLength) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentSelected =
|
||||
currentLine >= markers[markersLength - 1].line
|
||||
? markersLength - 1
|
||||
: markers.findIndex((marker) => marker.line > currentLine) - 1;
|
||||
|
||||
const currentSelectedType = markers[Math.max(0, currentSelected)].type;
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiRange
|
||||
|
@ -68,35 +80,38 @@ export const TTYPlayerControlsMarkers = ({
|
|||
showRange
|
||||
css={styles.range}
|
||||
/>
|
||||
<PlayHead
|
||||
css={styles.playHead(currentSelectedType)}
|
||||
style={{ left: `${(currentLine * 100) / linesLength}%` }}
|
||||
/>
|
||||
<PlayHead css={styles.playHead(currentSelectedType)} />
|
||||
<div css={styles.markersOverlay}>
|
||||
{markers.map(({ line, type }, idx) => {
|
||||
{markers.map(({ line, type, name }, idx) => {
|
||||
const selected =
|
||||
currentLine >= line &&
|
||||
(idx === markersLength - 1 || currentLine < markers[idx + 1].line);
|
||||
|
||||
// markers positions are absolute, setting higher z-index on the selected one in case there
|
||||
// are severals next to each other
|
||||
const style = {
|
||||
left: `${(line * 100) / linesLength}%`,
|
||||
const markerWrapperPositioning = {
|
||||
left: `${(line / linesLength) * 100}%`,
|
||||
zIndex: selected ? 3 : 2,
|
||||
};
|
||||
|
||||
const onMarkerClick = () => onSeekLine(line);
|
||||
|
||||
return (
|
||||
<button
|
||||
key={idx}
|
||||
type="button"
|
||||
value={line}
|
||||
tabIndex={-1}
|
||||
title={type}
|
||||
css={styles.marker(type, selected)}
|
||||
style={style}
|
||||
>
|
||||
{type}
|
||||
</button>
|
||||
<div key={idx} style={markerWrapperPositioning} css={styles.markerWrapper}>
|
||||
<EuiToolTip title={name}>
|
||||
<button
|
||||
type="button"
|
||||
value={line}
|
||||
tabIndex={-1}
|
||||
title={type}
|
||||
css={styles.marker(type, selected)}
|
||||
onClick={onMarkerClick}
|
||||
aria-label={name}
|
||||
>
|
||||
{name}
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@ import { useEuiTheme } from '../../../hooks';
|
|||
|
||||
type TTYPlayerLineMarkerType = 'output' | 'data_limited';
|
||||
|
||||
export const useStyles = () => {
|
||||
export const useStyles = (progress: number) => {
|
||||
const { euiTheme, euiVars } = useEuiTheme();
|
||||
const cached = useMemo(() => {
|
||||
const { border } = euiTheme;
|
||||
|
@ -23,6 +23,12 @@ export const useStyles = () => {
|
|||
width: '100%',
|
||||
};
|
||||
|
||||
const markerWrapper: CSSObject = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
lineHeight: 0,
|
||||
};
|
||||
|
||||
const getMarkerBackgroundColor = (type: TTYPlayerLineMarkerType, selected: boolean) => {
|
||||
if (type === 'data_limited') {
|
||||
return euiVars.terminalOutputMarkerWarning;
|
||||
|
@ -36,7 +42,6 @@ export const useStyles = () => {
|
|||
const marker = (type: TTYPlayerLineMarkerType, selected: boolean): CSSObject => ({
|
||||
fontSize: 0,
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
padding: 0,
|
||||
width: 3,
|
||||
height: 12,
|
||||
|
@ -44,10 +49,8 @@ export const useStyles = () => {
|
|||
border: `${border.width.thick} solid ${euiVars.terminalOutputBackground}`,
|
||||
borderRadius: border.radius.small,
|
||||
boxSizing: 'content-box',
|
||||
top: 0,
|
||||
pointerEvents: 'none',
|
||||
marginLeft: '-3.5px',
|
||||
transition: 'left .5s ease-in-out .3s',
|
||||
transition: 'left .5s ease-in-out',
|
||||
});
|
||||
|
||||
const playHeadThumb: CSSObject = {
|
||||
|
@ -82,6 +85,9 @@ export const useStyles = () => {
|
|||
"input[type='range']::-moz-range-thumb": customThumb,
|
||||
'.euiRangeHighlight__progress': {
|
||||
backgroundColor: euiVars.euiColorVis0_behindText,
|
||||
width: progress + '%',
|
||||
borderBottomRightRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
},
|
||||
'.euiRangeSlider:focus ~ .euiRangeHighlight .euiRangeHighlight__progress': {
|
||||
backgroundColor: euiVars.euiColorVis0_behindText,
|
||||
|
@ -93,9 +99,10 @@ export const useStyles = () => {
|
|||
},
|
||||
};
|
||||
|
||||
const playHead = (type: TTYPlayerLineMarkerType): CSSObject => ({
|
||||
const playHead = (type?: TTYPlayerLineMarkerType): CSSObject => ({
|
||||
...playHeadThumb,
|
||||
position: 'absolute',
|
||||
left: progress + '%',
|
||||
top: 16,
|
||||
fill:
|
||||
type === 'data_limited'
|
||||
|
@ -105,11 +112,21 @@ export const useStyles = () => {
|
|||
|
||||
return {
|
||||
marker,
|
||||
markerWrapper,
|
||||
markersOverlay,
|
||||
range,
|
||||
playHead,
|
||||
};
|
||||
}, [euiTheme, euiVars]);
|
||||
}, [
|
||||
euiTheme,
|
||||
euiVars.euiColorVis0_behindText,
|
||||
euiVars.euiColorVis1,
|
||||
euiVars.terminalOutputBackground,
|
||||
euiVars.terminalOutputMarkerAccent,
|
||||
euiVars.terminalOutputMarkerWarning,
|
||||
euiVars.terminalOutputSliderBackground,
|
||||
progress,
|
||||
]);
|
||||
|
||||
return cached;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
|
||||
import {
|
||||
EuiButtonIcon,
|
||||
EuiButtonIconProps,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
import { Teletype } from '../../../common/types/process_tree';
|
||||
import { DEFAULT_TTY_FONT_SIZE } from '../../../common/constants';
|
||||
import { ZOOM_IN, ZOOM_FIT, ZOOM_OUT } from './translations';
|
||||
|
@ -19,6 +25,12 @@ export interface TTYTextSizerDeps {
|
|||
onFontSizeChanged(newSize: number): void;
|
||||
}
|
||||
|
||||
const commonButtonProps: Partial<EuiButtonIconProps> = {
|
||||
display: 'empty',
|
||||
size: 's',
|
||||
color: 'ghost',
|
||||
};
|
||||
|
||||
const LINE_HEIGHT_SCALE_RATIO = 1.3;
|
||||
const MINIMUM_FONT_SIZE = 2;
|
||||
const MAXIMUM_FONT_SIZE = 20;
|
||||
|
@ -88,25 +100,13 @@ export const TTYTextSizer = ({
|
|||
display={fit ? 'fill' : 'empty'}
|
||||
iconType={fit ? 'expand' : 'minimize'}
|
||||
onClick={onToggleFit}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<div css={styles.separator} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={ZOOM_IN}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj="sessionView:TTYZoomIn"
|
||||
aria-label={ZOOM_IN}
|
||||
iconType="plusInCircle"
|
||||
onClick={onZoomIn}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem component="span" css={styles.ratio}>
|
||||
{`${Math.round((fontSize / DEFAULT_TTY_FONT_SIZE) * 100)}%`}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={ZOOM_OUT}>
|
||||
<EuiButtonIcon
|
||||
|
@ -114,6 +114,21 @@ export const TTYTextSizer = ({
|
|||
aria-label={ZOOM_OUT}
|
||||
iconType="minusInCircle"
|
||||
onClick={onZoomOut}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem component="span" css={styles.ratio}>
|
||||
{`${Math.round((fontSize / DEFAULT_TTY_FONT_SIZE) * 100)}%`}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip content={ZOOM_IN}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj="sessionView:TTYZoomIn"
|
||||
aria-label={ZOOM_IN}
|
||||
iconType="plusInCircle"
|
||||
onClick={onZoomIn}
|
||||
{...commonButtonProps}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -16,14 +16,13 @@ export const useStyles = () => {
|
|||
|
||||
const ratio: CSSObject = {
|
||||
fontSize: size.m,
|
||||
color: colors.ghost,
|
||||
};
|
||||
|
||||
const separator: CSSObject = {
|
||||
background: colors.lightShade,
|
||||
height: size.xl,
|
||||
width: border.width.thin,
|
||||
marginLeft: size.xs,
|
||||
marginRight: size.xs,
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -11,7 +11,7 @@ export const ZOOM_IN = i18n.translate('xpack.sessionView.zoomIn', {
|
|||
});
|
||||
|
||||
export const ZOOM_FIT = i18n.translate('xpack.sessionView.zoomFit', {
|
||||
defaultMessage: 'Zoom fit',
|
||||
defaultMessage: 'Fit screen',
|
||||
});
|
||||
|
||||
export const ZOOM_OUT = i18n.translate('xpack.sessionView.zoomOut', {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue