core-components: split out LogViewerControls

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-12-05 18:00:37 +01:00
committed by blam
parent be8e706462
commit 8a71f91bf2
2 changed files with 98 additions and 78 deletions
@@ -17,16 +17,11 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import { FixedSizeList } from 'react-window';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import FilterListIcon from '@material-ui/icons/FilterList';
import { AnsiLine, AnsiProcessor } from './AnsiProcessor';
import { HEADER_SIZE, useStyles } from './styles';
import clsx from 'clsx';
import TextField from '@material-ui/core/TextField';
import { LogLine } from './LogLine';
import { LogViewerControls } from './LogViewerControls';
import { useToggle } from 'react-use';
export interface LogViewerProps {
@@ -85,78 +80,6 @@ function applySearchFilter(lines: AnsiLine[], searchText: string) {
};
}
function LogViewerControls(props: {
search: string;
onSearchChange: (search: string) => void;
resultIndex: number | undefined;
resultCount: number | undefined;
onResultIndexChange: (index: number) => void;
shouldFilter: boolean;
onToggleShouldFilter: () => void;
}) {
const { resultCount, onResultIndexChange, onToggleShouldFilter } = props;
const resultIndex = props.resultIndex ?? 0;
const increment = () => {
if (resultCount !== undefined) {
const next = resultIndex + 1;
onResultIndexChange(next >= resultCount ? 0 : next);
}
};
const decrement = () => {
if (resultCount !== undefined) {
const next = resultIndex - 1;
onResultIndexChange(next < 0 ? resultCount - 1 : next);
}
};
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
if (event.metaKey || event.ctrlKey || event.altKey) {
onToggleShouldFilter();
} else if (event.shiftKey) {
decrement();
} else {
increment();
}
}
};
return (
<>
{resultCount !== undefined && (
<>
<IconButton size="small" onClick={decrement}>
<ChevronLeftIcon />
</IconButton>
<Typography>
{Math.min(resultIndex + 1, resultCount)}/{resultCount}
</Typography>
<IconButton size="small" onClick={increment}>
<ChevronRightIcon />
</IconButton>
</>
)}
<TextField
size="small"
variant="standard"
placeholder="Search"
value={props.search}
onKeyPress={handleKeyPress}
onChange={e => props.onSearchChange(e.target.value)}
/>
<IconButton size="small" onClick={onToggleShouldFilter}>
{props.shouldFilter ? (
<FilterListIcon color="primary" />
) : (
<FilterListIcon color="disabled" />
)}
</IconButton>
</>
);
}
export function LogViewer(props: LogViewerProps) {
const classes = useStyles();
const listRef = useRef<FixedSizeList | null>(null);
@@ -0,0 +1,97 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import IconButton from '@material-ui/core/IconButton';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import FilterListIcon from '@material-ui/icons/FilterList';
export interface LogViewerControlsProps {
search: string;
onSearchChange: (search: string) => void;
resultIndex: number | undefined;
resultCount: number | undefined;
onResultIndexChange: (index: number) => void;
shouldFilter: boolean;
onToggleShouldFilter: () => void;
}
export function LogViewerControls(props: LogViewerControlsProps) {
const { resultCount, onResultIndexChange, onToggleShouldFilter } = props;
const resultIndex = props.resultIndex ?? 0;
const increment = () => {
if (resultCount !== undefined) {
const next = resultIndex + 1;
onResultIndexChange(next >= resultCount ? 0 : next);
}
};
const decrement = () => {
if (resultCount !== undefined) {
const next = resultIndex - 1;
onResultIndexChange(next < 0 ? resultCount - 1 : next);
}
};
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
if (event.metaKey || event.ctrlKey || event.altKey) {
onToggleShouldFilter();
} else if (event.shiftKey) {
decrement();
} else {
increment();
}
}
};
return (
<>
{resultCount !== undefined && (
<>
<IconButton size="small" onClick={decrement}>
<ChevronLeftIcon />
</IconButton>
<Typography>
{Math.min(resultIndex + 1, resultCount)}/{resultCount}
</Typography>
<IconButton size="small" onClick={increment}>
<ChevronRightIcon />
</IconButton>
</>
)}
<TextField
size="small"
variant="standard"
placeholder="Search"
value={props.search}
onKeyPress={handleKeyPress}
onChange={e => props.onSearchChange(e.target.value)}
/>
<IconButton size="small" onClick={onToggleShouldFilter}>
{props.shouldFilter ? (
<FilterListIcon color="primary" />
) : (
<FilterListIcon color="disabled" />
)}
</IconButton>
</>
);
}