core-components: split out LogViewerControls
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user