1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Introducing log search

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2020-10-20 13:44:54 +03:00
parent edf59c9efd
commit 7234d2eb7f
4 changed files with 64 additions and 3 deletions

View File

@ -8,14 +8,17 @@ import { Icon } from "../icon";
import { _i18n } from "../../i18n"; import { _i18n } from "../../i18n";
import { cssNames, downloadFile } from "../../utils"; import { cssNames, downloadFile } from "../../utils";
import { Pod } from "../../api/endpoints"; import { Pod } from "../../api/endpoints";
import { PodLogSearch } from "./pod-log-search";
interface Props { interface Props {
ready: boolean ready: boolean
tabId: string tabId: string
tabData: IPodLogsData tabData: IPodLogsData
logs: string[][] logs: string[]
save: (data: Partial<IPodLogsData>) => void save: (data: Partial<IPodLogsData>) => void
reload: () => void reload: () => void
onSearch: (query: string) => void
search: string
} }
export const PodLogControls = observer((props: Props) => { export const PodLogControls = observer((props: Props) => {
@ -24,6 +27,7 @@ export const PodLogControls = observer((props: Props) => {
const { selectedContainer, showTimestamps, previous } = tabData; const { selectedContainer, showTimestamps, previous } = tabData;
const since = podLogsStore.getTimestamps(podLogsStore.logs.get(tabId)[0]); const since = podLogsStore.getTimestamps(podLogsStore.logs.get(tabId)[0]);
const pod = new Pod(tabData.pod); const pod = new Pod(tabData.pod);
const toggleTimestamps = () => { const toggleTimestamps = () => {
save({ showTimestamps: !showTimestamps }); save({ showTimestamps: !showTimestamps });
} }
@ -110,6 +114,7 @@ export const PodLogControls = observer((props: Props) => {
onClick={downloadLogs} onClick={downloadLogs}
tooltip={_i18n._(t`Save`)} tooltip={_i18n._(t`Save`)}
/> />
<PodLogSearch onSearch={props.onSearch} search={props.search} />
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,25 @@
import React from "react";
import { observer } from "mobx-react";
import { cssNames } from "../../utils";
import { Input } from "../input";
interface Props {
onSearch: (query: string) => void
search: string
}
export const PodLogSearch = observer((props: Props) => {
const { onSearch, search } = props;
const setSearch = (query: string) => {
onSearch(query);
};
return (
<div className="PodLogsSearch">
<Input
className={cssNames("SearchInput")}
value={search}
onChange={setSearch}
/>
</div>
)
});

View File

@ -29,11 +29,18 @@
font-family: $font-monospace; font-family: $font-monospace;
font-size: smaller; font-size: smaller;
white-space: pre; white-space: pre;
-webkit-font-smoothing: auto; -webkit-font-smoothing: auto; // Better readability on non-retina screens
&:hover { &:hover {
// TODO: Use a theme var to styling
background: #35373a; background: #35373a;
} }
span {
border-radius: 2px;
background-color: #8cc474b8;
-webkit-font-smoothing: auto;
}
} }
} }
} }

View File

@ -27,6 +27,7 @@ export class PodLogs extends React.Component<Props> {
@observable ready = false; @observable ready = false;
@observable preloading = false; // Indicator for setting Spinner (loader) at the top of the logs @observable preloading = false; // Indicator for setting Spinner (loader) at the top of the logs
@observable showJumpToBottom = false; @observable showJumpToBottom = false;
@observable findQuery = ""; // A text from search field
private logsElement = React.createRef<HTMLDivElement>(); // A reference for outer container in VirtualList private logsElement = React.createRef<HTMLDivElement>(); // A reference for outer container in VirtualList
private lastLineIsShown = true; // used for proper auto-scroll content after refresh private lastLineIsShown = true; // used for proper auto-scroll content after refresh
@ -101,6 +102,14 @@ export class PodLogs extends React.Component<Props> {
} }
} }
/**
* Updating findQuery observable
* @param query {string} A text from search field
*/
onSearch(query: string) {
this.findQuery = query;
}
/** /**
* Computed prop which returns logs with or without timestamps added to each line * Computed prop which returns logs with or without timestamps added to each line
* @returns {Array} An array log items * @returns {Array} An array log items
@ -138,9 +147,22 @@ export class PodLogs extends React.Component<Props> {
*/ */
getLogRow = (index: number) => { getLogRow = (index: number) => {
const isSeparator = this.logs[index] === "---newlogs---"; // TODO: Use constant separator const isSeparator = this.logs[index] === "---newlogs---"; // TODO: Use constant separator
const { findQuery } = this;
const item = this.logs[index];
const contents: React.ReactElement[] = [];
if (findQuery) {
// If search is enabled, replace keyword with backgrounded <span> to "highlight" searchable text
const pieces = item.split(findQuery);
pieces.forEach((piece, index) => {
const overlay = index !== pieces.length - 1 ? <span>{findQuery}</span> : null
contents.push(
<>{piece}{overlay}</>
);
})
}
return ( return (
<div className={cssNames("LogRow", { separator: isSeparator })}> <div className={cssNames("LogRow", { separator: isSeparator })}>
{this.logs[index]} {contents.length > 1 ? contents : item}
</div> </div>
); );
} }
@ -207,6 +229,8 @@ export class PodLogs extends React.Component<Props> {
logs={this.logs} logs={this.logs}
save={this.save} save={this.save}
reload={this.reload} reload={this.reload}
search={this.findQuery}
onSearch={this.onSearch}
/> />
) )
return ( return (