diff --git a/josh-ui/src/App.tsx b/josh-ui/src/App.tsx
index cdf537c01..4ac9dadaa 100644
--- a/josh-ui/src/App.tsx
+++ b/josh-ui/src/App.tsx
@@ -221,6 +221,26 @@ function Changes() {
}
+function Search() {
+ const param = useStrictGetSearchParam()
+
+ useTitleEffect(`Search - ${param('repo')} - Josh`)
+
+ return
+
+
+
+
+}
+
function View() {
const param = useStrictGetSearchParam()
diff --git a/josh-ui/src/Search.tsx b/josh-ui/src/Search.tsx
new file mode 100644
index 000000000..47ebd95a7
--- /dev/null
+++ b/josh-ui/src/Search.tsx
@@ -0,0 +1,108 @@
+import React from "react";
+import {GraphQLClient} from 'graphql-request'
+import {getServer} from "./Server";
+import {NavigateCallback, NavigateTargetType, QUERY_CHANGES} from "./Navigation";
+import {match} from "ts-pattern";
+
+export type SearchBrowserProps = {
+ repo: string
+ filter: string
+ searchstr: string
+ rev: string
+ navigateCallback: NavigateCallback
+}
+
+type State = {
+ results: SearchResult[]
+ client: GraphQLClient
+}
+
+export class SearchResults extends React.Component {
+ state: State = {
+ results: [],
+ client: new GraphQLClient(`${getServer()}/~/graphql/${this.props.repo}`, {
+ mode: 'cors'
+ }),
+ };
+
+ startRequest() {
+ this.state.client.rawRequest(QUERY_SEARCH, {
+ searchstr: this.props.searchstr
+ filter: this.props.filter,
+ rev: this.props.rev
+ }).then((d) => {
+ const data = d.data
+
+ this.setState({
+ results: data.results
+ })
+ })
+ }
+
+ componentDidMount() {
+ this.startRequest()
+ }
+
+ componentDidUpdate(
+ prevProps: Readonly,
+ prevState: Readonly,
+ snapshot?: any)
+ {
+ if (prevProps !== this.props) {
+ this.setState({
+ results: [],
+ })
+
+ this.startRequest()
+ }
+ }
+
+ componentWillUnmount() {
+ // TODO cancel request?
+ }
+
+ renderList(values: SearchResult[]) {
+
+ const navigateBrowse = (rev: string, path: string, e: React.MouseEvent) => {
+ this.props.navigateCallback(NavigateTargetType.File, {
+ repo: this.props.repo,
+ path: path,
+ filter: this.props.filter,
+ rev: rev,
+ })
+ }
+
+ return values.map((ee) => {
+ let entry = ee.commit;
+ return
+
+
+ {entry.summary}
+
+
+ {ee.name.replace("refs/heads/","")}
+
+
+
+ {entry.hash.slice(0,6)}
+
+
+
+ })
+ }
+
+ render() {
+ if (this.state.refs.length === 0) {
+ return Loading...
+ } else {
+ return
+ {this.renderList(this.state.refs)}
+
+ }
+ }
+}