mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-24 05:29:51 +03:00
Refactor search functionality in project layout
This commit refactors the search functionality present in the project layout. Instead of using a debounced input event handler to update the search query, a form is now used to handle search submission. The search functionality in the search page has also been updated to use the query param instead of a writable store, and the fetchResultData function has been extracted for better readability. Changes: - Replace debounced input event handler with form submission in project layout - Update search functionality in search page to use query param - Extract fetchResultData function for better readability - Remove unnecessary context and store usage
This commit is contained in:
parent
aaba14e819
commit
a0eeeae645
@ -6,28 +6,15 @@
|
||||
import { onDestroy } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { currentProject } from '$lib/current_project';
|
||||
import { setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let data: LayoutData;
|
||||
let query: string;
|
||||
const searchTerm = writable('');
|
||||
setContext('searchTerm', searchTerm);
|
||||
|
||||
$: project = data.project;
|
||||
$: currentProject.set($project);
|
||||
|
||||
const debounce = <T extends (...args: any[]) => any>(fn: T, delay: number) => {
|
||||
let timeout: ReturnType<typeof setTimeout>;
|
||||
return (...args: any[]) => {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => fn(...args), delay);
|
||||
};
|
||||
};
|
||||
|
||||
const updateQuery = debounce(async () => {
|
||||
searchTerm.set(query);
|
||||
}, 500);
|
||||
const onSearchSubmit = () => goto(`/projects/${$project?.id}/search?q=${query}`);
|
||||
|
||||
function projectUrl(project: Project) {
|
||||
const gitUrl = project.api?.git_url;
|
||||
@ -68,20 +55,23 @@
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
<div class="flex w-48 max-w-lg rounded-md shadow-sm">
|
||||
<form
|
||||
on:submit|preventDefault={onSearchSubmit}
|
||||
class="flex w-48 max-w-lg rounded-md shadow-sm"
|
||||
>
|
||||
<input type="submit" class="hidden" />
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
id="search"
|
||||
placeholder="search history"
|
||||
bind:value={query}
|
||||
on:input={updateQuery}
|
||||
autocomplete="off"
|
||||
aria-label="Search input"
|
||||
class="block w-full min-w-0 flex-1 rounded border border-zinc-700 bg-zinc-800 p-[3px] px-2 pl-10 text-zinc-200 placeholder:text-zinc-500 sm:text-sm sm:leading-6"
|
||||
style=""
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
|
@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { search } from '$lib';
|
||||
import { getContext } from 'svelte';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { search, type SearchResult } from '$lib';
|
||||
import { listFiles } from '$lib/sessions';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { list as listDeltas, type Delta } from '$lib/deltas';
|
||||
import { CodeViewer } from '$lib/components';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
export let data: PageData;
|
||||
const { project } = data;
|
||||
@ -17,17 +16,38 @@
|
||||
filepath: string;
|
||||
highlight: string[];
|
||||
}[];
|
||||
let searchTerm: Writable<string> = getContext('searchTerm');
|
||||
let stopProcessing = false;
|
||||
|
||||
$: query = $page.url.searchParams.get('q');
|
||||
$: {
|
||||
stopProcessing = true;
|
||||
processedResults = [];
|
||||
if ($searchTerm) {
|
||||
fetchResults($project?.id ?? '', $searchTerm);
|
||||
if (query && $project?.id) {
|
||||
stopProcessing = true;
|
||||
processedResults = [];
|
||||
fetchResults($project.id, query);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchResultData = async ({
|
||||
sessionId,
|
||||
projectId,
|
||||
filePath,
|
||||
index,
|
||||
highlighted
|
||||
}: SearchResult) => {
|
||||
const [doc, deltas] = await Promise.all([
|
||||
listFiles({ projectId, sessionId, paths: [filePath] }).then((r) => r[filePath] ?? ''),
|
||||
listDeltas({ projectId, sessionId, paths: [filePath] })
|
||||
.then((r) => r[filePath] ?? [])
|
||||
.then((d) => d.slice(0, index + 1))
|
||||
]);
|
||||
return {
|
||||
doc,
|
||||
deltas,
|
||||
filepath: filePath,
|
||||
highlight: highlighted
|
||||
};
|
||||
};
|
||||
|
||||
const fetchResults = async (projectId: string, query: string) => {
|
||||
const results = await search({ projectId, query });
|
||||
stopProcessing = false;
|
||||
@ -37,22 +57,7 @@
|
||||
stopProcessing = false;
|
||||
return;
|
||||
}
|
||||
const { sessionId, projectId, filePath } = result;
|
||||
const [doc, deltas] = await Promise.all([
|
||||
listFiles({ projectId, sessionId, paths: [filePath] }).then((r) => r[filePath] ?? ''),
|
||||
listDeltas({ projectId, sessionId, paths: [filePath] })
|
||||
.then((r) => r[filePath] ?? [])
|
||||
.then((d) => d.slice(0, result.index + 1))
|
||||
]);
|
||||
processedResults = [
|
||||
...processedResults,
|
||||
{
|
||||
doc,
|
||||
deltas,
|
||||
filepath: filePath,
|
||||
highlight: result.highlighted
|
||||
}
|
||||
];
|
||||
processedResults = [...processedResults, await fetchResultData(result)];
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -60,12 +65,12 @@
|
||||
<figure class="mx-14 flex h-full flex-col gap-2">
|
||||
{#if processedResults.length > 0}
|
||||
<div class="mb-10 mt-14">
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Results for "{$searchTerm}"</p>
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Results for "{query}"</p>
|
||||
<p class="text-lg text-[#717179]">{processedResults.length} change instances</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mb-10 mt-14">
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">No results for "{$searchTerm}"</p>
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">No results for "{query}"</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user