mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-11 12:25:42 +03:00
Add pagination and improve search UI
This commit adds pagination support to the search results page by updating the limit of results per page, implementing openNextPage and openPrevPage functions, and including navigation buttons for the pagination. It also improves the UI by adding a spinning icon while searching for results and adjusts the overall styling for better readability. - Added IconChevronLeft and IconChevronRight to icons exports - Updated the limit of results per page from 50 to 10 - Implemented openNextPage and openPrevPage functions for pagination - Added navigation buttons for previous and next pages - Used IconRotateClockwise with animation for a spinning icon while searching - Updated the styling for better UI readability
This commit is contained in:
parent
3a372284e8
commit
4cc61cd8d4
15
src/lib/components/icons/IconChevronLeft.svelte
Normal file
15
src/lib/components/icons/IconChevronLeft.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<svg
|
||||
{...$$restProps}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M15 6l-6 6l6 6" />
|
||||
</svg>
|
After Width: | Height: | Size: 300 B |
15
src/lib/components/icons/IconChevronRight.svelte
Normal file
15
src/lib/components/icons/IconChevronRight.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<svg
|
||||
{...$$restProps}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M9 6l6 6l-6 6" />
|
||||
</svg>
|
After Width: | Height: | Size: 299 B |
@ -14,3 +14,5 @@ export { default as IconSquareRoundedFilled } from './IconSquareRoundedFilled.sv
|
||||
export { default as IconMapPinFilled } from './IconMapPinFilled.svelte';
|
||||
export { default as IconCircleFilled } from './IconCircleFilled.svelte';
|
||||
export { default as IconCircleCancel } from './IconCircleCancel.svelte';
|
||||
export { default as IconChevronLeft } from './IconChevronLeft.svelte';
|
||||
export { default as IconChevronRight } from './IconChevronRight.svelte';
|
||||
|
@ -1,21 +1,27 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { search, type SearchResult } from '$lib';
|
||||
import { IconChevronLeft, IconChevronRight } from '$lib/components/icons';
|
||||
import { listFiles } from '$lib/sessions';
|
||||
import { asyncDerived } from '@square/svelte-store';
|
||||
import { IconRotateClockwise } from '$lib/components/icons';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { list as listDeltas } from '$lib/deltas';
|
||||
import { CodeViewer } from '$lib/components';
|
||||
import { page } from '$app/stores';
|
||||
import { derived } from 'svelte/store';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let data: PageData;
|
||||
const { project } = data;
|
||||
|
||||
const limit = 50;
|
||||
const limit = 10;
|
||||
const query = derived(page, (page) => page.url.searchParams.get('q'));
|
||||
const offset = derived(page, (page) => parseInt(page.url.searchParams.get('offset') ?? '0'));
|
||||
|
||||
const openNextPage = () => goto(`?q=${$query}&offset=${$offset + limit}`);
|
||||
const openPrevPage = () => goto(`?q=${$query}&offset=${$offset - limit}`);
|
||||
|
||||
const fetchResultData = async ({
|
||||
sessionId,
|
||||
projectId,
|
||||
@ -40,11 +46,12 @@
|
||||
const { store: searchResults, state: searchState } = asyncDerived(
|
||||
[query, project, offset],
|
||||
async ([query, project, offset]) => {
|
||||
if (!query || !project) return { page: [], total: 0, haveMore: false };
|
||||
if (!query || !project) return { page: [], total: 0, haveNext: false, havePrev: false };
|
||||
const results = await search({ projectId: project.id, query, limit, offset });
|
||||
return {
|
||||
page: await Promise.all(results.page.map(fetchResultData)),
|
||||
haveMore: offset + limit < results.total,
|
||||
haveNext: offset + limit < results.total,
|
||||
havePrev: offset > 0,
|
||||
total: results.total
|
||||
};
|
||||
},
|
||||
@ -52,17 +59,21 @@
|
||||
);
|
||||
</script>
|
||||
|
||||
<figure class="search-results flex h-full flex-col gap-2">
|
||||
<figure id="search-results" class="flex h-full flex-col gap-10 p-14">
|
||||
{#if $searchState?.isLoading || $searchState?.isReloading}
|
||||
<figcaption class="m-auto">
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Looking for "{$query}"...</p>
|
||||
<figcaption>
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Searching for "{$query}"...</p>
|
||||
</figcaption>
|
||||
|
||||
<div class="mx-auto">
|
||||
<IconRotateClockwise class="h-20 w-20 animate-spin" />
|
||||
</div>
|
||||
{:else if $searchState?.isError}
|
||||
<figcaption class="m-auto">
|
||||
<figcaption>
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Error searching for "{$query}"</p>
|
||||
</figcaption>
|
||||
{:else if $searchState?.isLoaded}
|
||||
<figcaption class="mx-14 mb-10 mt-14">
|
||||
<figcaption>
|
||||
{#if $searchResults.total > 0}
|
||||
<p class="mb-2 text-xl text-[#D4D4D8]">Results for "{$query}"</p>
|
||||
<p class="text-lg text-[#717179]">{$searchResults.total} change instances</p>
|
||||
@ -71,7 +82,7 @@
|
||||
{/if}
|
||||
</figcaption>
|
||||
|
||||
<ul class="px-14 flex-auto overflow-auto">
|
||||
<ul class="flex-auto overflow-auto">
|
||||
{#each $searchResults.page as { doc, deltas, filepath, highlight }}
|
||||
{@const timestamp = deltas[deltas.length - 1].timestampMs}
|
||||
<li class="mt-6">
|
||||
@ -89,5 +100,24 @@
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<nav class="mx-auto flex rounded-md border border-zinc-700 text-zinc-400">
|
||||
<button
|
||||
on:click={openPrevPage}
|
||||
disabled={!$searchResults.havePrev}
|
||||
class:text-zinc-50={$searchResults.havePrev}
|
||||
class="h-9 w-9"
|
||||
>
|
||||
<IconChevronLeft class="ml-1 h-5 w-6" />
|
||||
</button>
|
||||
<button
|
||||
on:click={openNextPage}
|
||||
disabled={!$searchResults.haveNext}
|
||||
class:text-zinc-50={$searchResults.haveNext}
|
||||
class="h-9 w-9 border-l border-zinc-700"
|
||||
>
|
||||
<IconChevronRight class="ml-1 h-5 w-6" />
|
||||
</button>
|
||||
</nav>
|
||||
{/if}
|
||||
</figure>
|
||||
|
Loading…
Reference in New Issue
Block a user