-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Search is now a separate page from the home page which shows recent searches. The search page accepts a few query parameters: * query - the string to search for * startTime - the absolute start time of the search * endTime - the absolute end time of the search * relativeTime - the relative duration of the search, or "ALL" to search without filtering by time * jobId - The ID of a previously started job to use the results from The really big win here is that you can now link Logsuck searches to someone else, whereas previously the URL would always just be "/". The current design does not use client side routing. I don't feel the complexity of adding client side routing at this stage is worth it. Currently each page also gets its own bundle, meaning the entire Preact library is downloaded for each page. This is a microscopic performance issue that I might fix at some point but it doesn't seem worth prioritizing. A fairly simple improvement that can be made is to save the current page from the pagination into the URL so you can also link to a specific result page. I'm not sure the behavior with the jobId param leading to job results being reused is intuitive - maybe it will lead to confusion when you get stale results, but I'm trying it out for now.
- Loading branch information
1 parent
0d1ee27
commit 0be0767
Showing
15 changed files
with
1,232 additions
and
740 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* Copyright 2021 The Logsuck 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 { h } from "preact"; | ||
import { LogEvent } from "../models/Event"; | ||
|
||
export interface EventTableProps { | ||
events: LogEvent[]; | ||
} | ||
|
||
export const EventTable = ({ events }: EventTableProps) => ( | ||
<table class="table table-hover search-result-table"> | ||
<thead> | ||
<tr> | ||
<th scope="col">Time</th> | ||
<th scope="col">Event</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{events.map((e) => ( | ||
<tr key={e.raw}> | ||
<td class="event-timestamp">{e.timestamp.toLocaleString()}</td> | ||
<td> | ||
<div | ||
style={{ | ||
display: "flex", | ||
flexDirection: "column", | ||
}} | ||
> | ||
<div class="event-raw">{e.raw}</div> | ||
<hr | ||
style={{ | ||
width: "100%", | ||
marginTop: "0.75rem", | ||
marginBottom: "0.5rem", | ||
}} | ||
/> | ||
<div class="event-additional"> | ||
<dl class="row no-gutters" style={{ marginBottom: 0 }}> | ||
<dt class="col-1">source</dt> | ||
<dd class="col-1">{e.source}</dd> | ||
</dl> | ||
</div> | ||
</div> | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/** | ||
* Copyright 2021 The Logsuck 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 { h } from "preact"; | ||
|
||
export interface FieldTableProps { | ||
fields: { [key: string]: number }; | ||
onFieldClicked: (str: string) => void; | ||
} | ||
|
||
export const FieldTable = ({ fields, onFieldClicked }: FieldTableProps) => { | ||
const keys = Object.keys(fields); | ||
return ( | ||
<div> | ||
{keys.length === 0 && <div>No fields extracted</div>} | ||
{keys.length > 0 && ( | ||
<table class="table table-sm table-hover"> | ||
<tbody> | ||
{keys.map((k) => ( | ||
<tr | ||
key={k} | ||
onClick={(evt) => { | ||
evt.stopPropagation(); | ||
onFieldClicked(k); | ||
}} | ||
class="test field-row" | ||
> | ||
<td>{k}</td> | ||
<td style={{ textAlign: "right" }}>{fields[k]}</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
)} | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* Copyright 2021 The Logsuck 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 { h } from "preact"; | ||
import { TopFieldValueInfo } from "../models/TopFieldValueInfo"; | ||
|
||
export interface FieldValueTableProps { | ||
values: TopFieldValueInfo[]; | ||
onFieldValueClicked: (value: string) => void; | ||
} | ||
|
||
export const FieldValueTable = ({ | ||
values, | ||
onFieldValueClicked, | ||
}: FieldValueTableProps) => ( | ||
<table class="table table-sm table-hover"> | ||
<tbody> | ||
{values.map((f) => ( | ||
<tr | ||
key={f.value} | ||
onClick={() => onFieldValueClicked(f.value)} | ||
style={{ cursor: "pointer" }} | ||
> | ||
<td class="field-value">{f.value}</td> | ||
<td class="field-value-count" style={{ textAlign: "right" }}> | ||
{f.count} | ||
</td> | ||
<td class="field-value-percentage" style={{ textAlign: "right" }}> | ||
{(f.percentage * 100).toFixed(2)} % | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright 2021 The Logsuck 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 { h } from "preact"; | ||
|
||
export const Navbar = () => ( | ||
<header> | ||
<nav class="navbar navbar-dark bg-dark"> | ||
<a href="/" class="navbar-brand"> | ||
logsuck | ||
</a> | ||
<a href="/search">Search</a> | ||
</nav> | ||
</header> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* Copyright 2021 The Logsuck 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 { h, Component } from "preact"; | ||
import { TimeSelect } from "./TimeSelect"; | ||
import { TimeSelection } from "../models/TimeSelection"; | ||
import { createSearchUrl } from "../createSearchUrl"; | ||
|
||
export interface SearchInputProps { | ||
isButtonDisabled: boolean; | ||
searchString: string; | ||
setSearchString: (str: string) => void; | ||
selectedTime: TimeSelection; | ||
setSelectedTime: (ts: TimeSelection) => void; | ||
|
||
onSearch: () => void; | ||
} | ||
|
||
export const SearchInput = (props: SearchInputProps) => ( | ||
<div class="search-container"> | ||
<form | ||
onSubmit={(evt) => { | ||
evt.preventDefault(); | ||
props.onSearch(); | ||
}} | ||
> | ||
<label htmlFor="searchinput">Search</label> | ||
<div class="input-group mb-3"> | ||
<input | ||
id="searchinput" | ||
type="text" | ||
class="form-control" | ||
onInput={(evt) => props.setSearchString((evt.target as any).value)} | ||
value={props.searchString} | ||
/> | ||
<div class="input-group-append"> | ||
<TimeSelect | ||
selection={props.selectedTime} | ||
onTimeSelected={(ts) => props.setSelectedTime(ts)} | ||
/> | ||
<button | ||
disabled={props.isButtonDisabled} | ||
type="submit" | ||
class="btn btn-primary" | ||
> | ||
Search | ||
</button> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
); | ||
|
||
export interface RedirectSearchInputProps { | ||
navigateTo: (url: string) => void; | ||
} | ||
|
||
interface RedirectSearchInputState { | ||
searchString: string; | ||
timeSelection: TimeSelection; | ||
} | ||
|
||
/** | ||
* RedirectSearchInput is an easier to use version of SearchInput which can be used on pages which don't need to do anything special with the input. | ||
* RedirectSearchInput will navigate to the resulting search URL when the search button is clicked. | ||
*/ | ||
export class RedirectSearchInput extends Component< | ||
RedirectSearchInputProps, | ||
RedirectSearchInputState | ||
> { | ||
constructor(props: RedirectSearchInputProps) { | ||
super(props); | ||
this.state = { | ||
searchString: "", | ||
timeSelection: {}, | ||
}; | ||
} | ||
|
||
render() { | ||
return ( | ||
<SearchInput | ||
isButtonDisabled={false} | ||
searchString={this.state.searchString} | ||
setSearchString={(str) => this.setState({ searchString: str })} | ||
selectedTime={this.state.timeSelection} | ||
setSelectedTime={(ts) => this.setState({ timeSelection: ts })} | ||
onSearch={() => | ||
this.props.navigateTo( | ||
createSearchUrl(this.state.searchString, this.state.timeSelection) | ||
) | ||
} | ||
/> | ||
); | ||
} | ||
} |
Oops, something went wrong.