Просмотр исходного кода

Add search functionality to logs live feed

This commit adds search functionality to the logs live feed, allowing
users to live stream lines based on their search query.

Changes:
- Added `search` state to `LogsPage.tsx` and passed it down to
`StreamText.tsx`.
- Added `SearchInput` component to `StreamText.tsx` header.
- Updated `liveFeed` prop in `LogsPage.tsx` to filter logs based on the
search query.
- Refactored the styling of log severity pills in `StreamText.tsx`.
Sergiu Miclea 3 лет назад
Родитель
Сommit
ea1a116b40

+ 9 - 1
src/components/smart/LogStreamPage/LogStreamPage.tsx

@@ -31,6 +31,7 @@ type State = {
   logName: string;
   severityLevel: number;
   isStreaming: boolean;
+  search: string;
 };
 @observer
 class LogStreamPage extends React.Component<Record<string, never>, State> {
@@ -38,6 +39,7 @@ class LogStreamPage extends React.Component<Record<string, never>, State> {
     logName: "All Logs",
     severityLevel: 6,
     isStreaming: true,
+    search: "",
   };
 
   UNSAFE_componentWillMount() {
@@ -112,10 +114,16 @@ class LogStreamPage extends React.Component<Record<string, never>, State> {
     return (
       <Wrapper>
         <StreamText
+          search={this.state.search}
+          onSearchChange={search => {
+            this.setState({ search });
+          }}
           logName={this.state.logName}
           logs={[{ log_name: "All Logs" }, ...logStore.logs]}
           severityLevel={this.state.severityLevel}
-          liveFeed={logStore.liveFeed}
+          liveFeed={logStore.liveFeed.filter(l =>
+            l.includes(this.state.search)
+          )}
           onLogNameChange={logName => {
             this.handleLogNameChange(logName);
           }}

+ 10 - 2
src/components/smart/LogsPage/LogsPage.tsx

@@ -50,14 +50,16 @@ type State = {
   streamLogName: string;
   streamSeverityLevel: number;
   isStreaming: boolean;
+  search: string;
 };
 @observer
 class LogsPage extends React.Component<Record<string, never>, State> {
-  state = {
+  state: State = {
     selectedTab: "downloads",
     streamLogName: "All Logs",
     streamSeverityLevel: 6,
     isStreaming: true,
+    search: "",
   };
 
   UNSAFE_componentWillMount() {
@@ -188,10 +190,16 @@ class LogsPage extends React.Component<Record<string, never>, State> {
         return (
           <TabContent>
             <StreamText
+              search={this.state.search}
+              onSearchChange={search => {
+                this.setState({ search });
+              }}
               logName={this.state.streamLogName}
               logs={[{ log_name: "All Logs" }, ...logStore.logs]}
               severityLevel={this.state.streamSeverityLevel}
-              liveFeed={logStore.liveFeed}
+              liveFeed={logStore.liveFeed.filter(l =>
+                l.includes(this.state.search)
+              )}
               onLogNameChange={logName => {
                 this.handleStreamLogNameChange(logName);
               }}

+ 57 - 36
src/components/smart/LogsPage/StreamText.tsx

@@ -19,6 +19,7 @@ import AnsiToHtml from "ansi-to-html";
 
 import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink";
 import Checkbox from "@src/components/ui/Checkbox";
+import SearchInput from "@src/components/ui/SearchInput";
 
 import { ThemePalette, ThemeProps } from "@src/components/Theme";
 
@@ -34,11 +35,14 @@ const Wrapper = styled.div<any>`
 `;
 const Header = styled.div<any>`
   display: flex;
-  justify-content: flex-end;
+  justify-content: space-between;
   flex-shrink: 0;
   margin-bottom: 8px;
   align-items: center;
 `;
+const Column = styled.div`
+  display: flex;
+`;
 const DropdownLinkStyled = styled(DropdownLink)`
   margin-left: 16px;
 `;
@@ -74,6 +78,7 @@ const AutoscrollLabel = styled.div<any>`
 `;
 const FeedLine = styled.div<any>`
   word-break: break-word;
+  margin-bottom: 8px;
 `;
 const TextButton = styled.div<any>`
   color: ${ThemePalette.grayscale[3]};
@@ -88,14 +93,19 @@ const ERROR_COLOR = "#c80546";
 const INFO_COLOR = "#747474";
 const WARNING_COLOR = "#cb9002";
 const GlobalStyle = createGlobalStyle`
-  .streamTextPill-EMERGENCY { color: ${ERROR_COLOR}; }
-  .streamTextPill-ALERT { color: ${ERROR_COLOR}; }
-  .streamTextPill-CRITICAL { color: ${ERROR_COLOR}; }
-  .streamTextPill-ERROR { color: ${ERROR_COLOR}; }
-  .streamTextPill-WARNING { color: ${WARNING_COLOR}; }
-  .streamTextPill-NOTICE { color: ${WARNING_COLOR}; }
-  .streamTextPill-INFO { color: ${INFO_COLOR}; }
-  .streamTextPill-DEBUG { color: ${WARNING_COLOR}; }
+  .streamTextPill {
+    color: white;
+    padding: 2px;
+    border-radius: 4px;
+  }
+  .streamTextPill.EMERGENCY { background: ${ERROR_COLOR}; }
+  .streamTextPill.ALERT { background: ${ERROR_COLOR}; }
+  .streamTextPill.CRITICAL { background: ${ERROR_COLOR}; }
+  .streamTextPill.ERROR { background: ${ERROR_COLOR}; }
+  .streamTextPill.WARNING { background: ${WARNING_COLOR}; }
+  .streamTextPill.NOTICE { background: ${WARNING_COLOR}; }
+  .streamTextPill.INFO { background: ${INFO_COLOR}; }
+  .streamTextPill.DEBUG { background: ${INFO_COLOR}; }
 `;
 const SEVERITY_LEVELS = [
   { value: 0, label: "Emergency" },
@@ -112,6 +122,8 @@ type Props = {
   logs: Log[];
   logName: string;
   severityLevel: number;
+  search: string;
+  onSearchChange: (search: string) => void;
   onLogNameChange: (logName: string) => void;
   onSeverityLevelChange: (level: number) => void;
   disableOpenInNewWindow?: boolean;
@@ -187,33 +199,42 @@ class StreamText extends React.Component<Props, State> {
       <Wrapper>
         <GlobalStyle />
         <Header>
-          <TextButton onClick={this.props.onStopPlayClick}>
-            {this.props.stopPlayLabel}
-          </TextButton>
-          <TextButton onClick={this.props.onClearClick}>Clear</TextButton>
-          <DropdownLinkStyled
-            items={SEVERITY_LEVELS}
-            selectedItem={this.props.severityLevel}
-            onChange={item => {
-              this.props.onSeverityLevelChange(Number(item.value));
-            }}
-          />
-          <DropdownLinkStyled
-            items={this.props.logs.map(l => ({
-              label: l.log_name,
-              value: l.log_name,
-            }))}
-            selectedItem={this.props.logName}
-            onChange={item => {
-              this.props.onLogNameChange(String(item.value));
-            }}
-          />
-          {!this.props.disableOpenInNewWindow ? (
-            <OpenInNewWindow
-              href={`streamlog?logName=${this.props.logName}&severity=${this.props.severityLevel}`}
-              target="_blank"
+          <Column>
+            <SearchInput
+              alwaysOpen
+              value={this.props.search}
+              onChange={this.props.onSearchChange}
+            />
+          </Column>
+          <Column>
+            <TextButton onClick={this.props.onStopPlayClick}>
+              {this.props.stopPlayLabel}
+            </TextButton>
+            <TextButton onClick={this.props.onClearClick}>Clear</TextButton>
+            <DropdownLinkStyled
+              items={SEVERITY_LEVELS}
+              selectedItem={this.props.severityLevel}
+              onChange={item => {
+                this.props.onSeverityLevelChange(Number(item.value));
+              }}
             />
-          ) : null}
+            <DropdownLinkStyled
+              items={this.props.logs.map(l => ({
+                label: l.log_name,
+                value: l.log_name,
+              }))}
+              selectedItem={this.props.logName}
+              onChange={item => {
+                this.props.onLogNameChange(String(item.value));
+              }}
+            />
+            {!this.props.disableOpenInNewWindow ? (
+              <OpenInNewWindow
+                href={`streamlog?logName=${this.props.logName}&severity=${this.props.severityLevel}`}
+                target="_blank"
+              />
+            ) : null}
+          </Column>
         </Header>
         <Content
           ref={(ref: HTMLElement) => {
@@ -227,7 +248,7 @@ class StreamText extends React.Component<Props, State> {
             const exp =
               /(^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) (.*?)\s/gm;
             const newFeed = feed
-              .replace(exp, '$1 <span class="streamTextPill-$2">$2</span> ')
+              .replace(exp, '$1 <span class="streamTextPill $2">$2</span> ')
               .replace(/\n/g, "<br />");
             return (
               <FeedLine