2024-08-25 00:45:44 +00:00
|
|
|
'use client';
|
|
|
|
|
|
2024-08-23 20:54:13 +00:00
|
|
|
import Image from "next/image";
|
2024-08-25 00:45:44 +00:00
|
|
|
import logo from "../../public/sb_logo_large_3.png"
|
|
|
|
|
import { Input } from "@/components/ui/input"
|
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
import { useDebouncedCallback } from 'use-debounce';
|
|
|
|
|
import { Separator } from "@/components/ui/separator"
|
|
|
|
|
|
|
|
|
|
interface ZoekMatch {
|
|
|
|
|
URL: string,
|
|
|
|
|
FileName: string,
|
|
|
|
|
LineNum: number,
|
|
|
|
|
Fragments: {
|
|
|
|
|
Pre: string,
|
|
|
|
|
Match: string,
|
|
|
|
|
Post: string
|
|
|
|
|
}[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface ZoekFileMatch {
|
|
|
|
|
FileName: string,
|
|
|
|
|
Repo: string,
|
|
|
|
|
Language: string,
|
|
|
|
|
Matches: ZoekMatch[],
|
|
|
|
|
URL: string,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface ZoekSearchResult {
|
|
|
|
|
result: {
|
|
|
|
|
QueryStr: string,
|
|
|
|
|
FileMatches: ZoekFileMatch[] | null,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 20:54:13 +00:00
|
|
|
|
|
|
|
|
export default function Home() {
|
|
|
|
|
|
2024-08-25 00:45:44 +00:00
|
|
|
const [fileMatches, setFileMatches] = useState<ZoekFileMatch[]>([]);
|
|
|
|
|
|
|
|
|
|
const onSearchChanged = useDebouncedCallback((query: string) => {
|
|
|
|
|
if (query === "") {
|
|
|
|
|
setFileMatches([]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
console.log('making query...');
|
|
|
|
|
fetch(`${document.baseURI}/zoekt/search?query=${query}&numResults=50`)
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(({ data }: { data: ZoekSearchResult }) => {
|
|
|
|
|
const result = data.result;
|
|
|
|
|
setFileMatches(result.FileMatches ?? []);
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
console.log('done making query');
|
|
|
|
|
})
|
|
|
|
|
}, 200);
|
2024-08-23 20:54:13 +00:00
|
|
|
|
2024-08-25 00:45:44 +00:00
|
|
|
return (
|
|
|
|
|
<main className="flex h-screen flex-col">
|
|
|
|
|
<div className="flex flex-row p-2 gap-4 items-center">
|
|
|
|
|
<Image
|
|
|
|
|
src={logo}
|
|
|
|
|
className="h-12 w-auto"
|
|
|
|
|
alt={"Sourcebot logo"}
|
|
|
|
|
/>
|
|
|
|
|
<Input
|
|
|
|
|
className="max-w-lg"
|
|
|
|
|
placeholder="Search..."
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const query = e.target.value;
|
|
|
|
|
onSearchChanged(query);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<Separator />
|
|
|
|
|
<div className="bg-accent p-2">
|
|
|
|
|
<p className="text-sm font-medium">Results for: {fileMatches.length} files</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col gap-2">
|
|
|
|
|
{fileMatches.map((match, index) => (
|
|
|
|
|
<FileMatch key={index} match={match} />
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-08-23 20:54:13 +00:00
|
|
|
|
2024-08-25 00:45:44 +00:00
|
|
|
interface FileMatchProps {
|
|
|
|
|
match: ZoekFileMatch;
|
|
|
|
|
}
|
2024-08-23 20:54:13 +00:00
|
|
|
|
2024-08-25 00:45:44 +00:00
|
|
|
const FileMatch = ({
|
|
|
|
|
match,
|
|
|
|
|
}: FileMatchProps) => {
|
2024-08-23 20:54:13 +00:00
|
|
|
|
2024-08-25 00:45:44 +00:00
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<p><span className="font-bold">{match.Repo}</span> | {match.FileName}</p>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2024-08-23 20:54:13 +00:00
|
|
|
}
|