Skip to content

Commit 25a7ba5

Browse files
Mishiggary149
andauthored
[Assistants] Add pagination (#772)
* [Assistants] Add pagination * Update src/lib/components/PaginationArrow.svelte Co-authored-by: Victor Muštar <victor.mustar@gmail.com> * format * Simplify by using a href * this statement needs to be reactive * simplify pagination * update disabled * Update src/routes/assistants/+page.server.ts --------- Co-authored-by: Victor Muštar <victor.mustar@gmail.com>
1 parent b3c073e commit 25a7ba5

File tree

4 files changed

+148
-4
lines changed

4 files changed

+148
-4
lines changed

src/lib/components/Pagination.svelte

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<script lang="ts">
2+
import { page } from "$app/stores";
3+
import PaginationArrow from "./PaginationArrow.svelte";
4+
5+
export let classNames = "";
6+
export let numItemsPerPage: number;
7+
export let numTotalItems: number;
8+
9+
const ELLIPSIS_IDX = -1 as const;
10+
11+
const numTotalPages = Math.ceil(numTotalItems / numItemsPerPage);
12+
$: pageIndex = parseInt($page.url.searchParams.get("p") ?? "0");
13+
$: pageIndexes = getPageIndexes(pageIndex);
14+
15+
function getHref(pageIdx: number) {
16+
const newUrl = new URL($page.url);
17+
newUrl.searchParams.set("p", pageIdx.toString());
18+
return newUrl.toString();
19+
}
20+
21+
function getPageIndexes(pageIdx: number) {
22+
let pageIdxs: number[] = [];
23+
24+
const NUM_EXTRA_BUTTONS = 2; // The number of page links to show on either side of the current page link.
25+
26+
const minIdx = 0;
27+
const maxIdx = numTotalPages - 1;
28+
29+
pageIdxs = [pageIdx];
30+
31+
// forward
32+
for (let i = 1; i < NUM_EXTRA_BUTTONS + 1; i++) {
33+
const newPageIdx = pageIdx + i;
34+
if (newPageIdx > maxIdx) {
35+
continue;
36+
}
37+
pageIdxs.push(newPageIdx);
38+
}
39+
if (maxIdx - pageIdxs[pageIdxs.length - 1] > 1) {
40+
pageIdxs.push(...[ELLIPSIS_IDX, maxIdx]);
41+
} else if (maxIdx - pageIdxs[pageIdxs.length - 1] === 1) {
42+
pageIdxs.push(maxIdx);
43+
}
44+
45+
// backward
46+
for (let i = 1; i < NUM_EXTRA_BUTTONS + 1; i++) {
47+
const newPageIdx = pageIdx - i;
48+
if (newPageIdx < minIdx) {
49+
continue;
50+
}
51+
pageIdxs.unshift(newPageIdx);
52+
}
53+
if (pageIdxs[0] - minIdx > 1) {
54+
pageIdxs.unshift(...[minIdx, ELLIPSIS_IDX]);
55+
} else if (pageIdxs[0] - minIdx === 1) {
56+
pageIdxs.unshift(minIdx);
57+
}
58+
return pageIdxs;
59+
}
60+
</script>
61+
62+
{#if numTotalPages > 1}
63+
<nav>
64+
<ul
65+
class="flex select-none items-center justify-between space-x-2 text-gray-700 sm:justify-center dark:text-gray-300 {classNames}"
66+
>
67+
<li>
68+
<PaginationArrow
69+
href={getHref(pageIndex - 1)}
70+
direction="previous"
71+
isDisabled={pageIndex - 1 < 0}
72+
/>
73+
</li>
74+
{#each pageIndexes as pageIdx}
75+
<li class="hidden sm:block">
76+
<a
77+
class="
78+
rounded-lg px-2.5 py-1
79+
{pageIndex === pageIdx
80+
? 'bg-gray-50 font-semibold ring-1 ring-inset ring-gray-200 dark:bg-gray-800 dark:text-yellow-500 dark:ring-gray-700'
81+
: ''}
82+
"
83+
class:pointer-events-none={pageIdx === ELLIPSIS_IDX || pageIndex === pageIdx}
84+
href={getHref(pageIdx)}
85+
>
86+
{pageIdx === ELLIPSIS_IDX ? "..." : pageIdx + 1}
87+
</a>
88+
</li>
89+
{/each}
90+
<li>
91+
<PaginationArrow
92+
href={getHref(pageIndex + 1)}
93+
direction="next"
94+
isDisabled={pageIndex + 1 >= numTotalPages}
95+
/>
96+
</li>
97+
</ul>
98+
</nav>
99+
{/if}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script lang="ts">
2+
import CarbonCaretLeft from "~icons/carbon/caret-left";
3+
import CarbonCaretRight from "~icons/carbon/caret-right";
4+
5+
export let href: string;
6+
export let direction: "next" | "previous";
7+
export let isDisabled = false;
8+
</script>
9+
10+
<a
11+
class="flex items-center rounded-lg px-2.5 py-1 hover:bg-gray-50 dark:hover:bg-gray-800 {isDisabled
12+
? 'pointer-events-none opacity-50'
13+
: ''}"
14+
{href}
15+
>
16+
{#if direction === "previous"}
17+
<CarbonCaretLeft classNames="mr-1.5" />
18+
Previous
19+
{:else}
20+
Next
21+
<CarbonCaretRight classNames="ml-1.5" />
22+
{/if}
23+
</a>

src/routes/assistants/+page.server.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,36 @@ import { ENABLE_ASSISTANTS } from "$env/static/private";
33
import { collections } from "$lib/server/database.js";
44
import type { Assistant } from "$lib/types/Assistant";
55
import { redirect } from "@sveltejs/kit";
6+
import type { Filter } from "mongodb";
7+
8+
const NUM_PER_PAGE = 24;
69

710
export const load = async ({ url }) => {
811
if (!ENABLE_ASSISTANTS) {
912
throw redirect(302, `${base}/`);
1013
}
1114

1215
const modelId = url.searchParams.get("modelId");
16+
const pageIndex = parseInt(url.searchParams.get("p") ?? "0");
1317

14-
// fetch the top 10 assistants sorted by user count from biggest to smallest, filter out all assistants with only 1 users. filter by model too if modelId is provided
18+
// fetch the top assistants sorted by user count from biggest to smallest, filter out all assistants with only 1 users. filter by model too if modelId is provided
19+
const filter: Filter<Assistant> = {
20+
userCount: { $gt: 1 },
21+
modelId: modelId ?? { $exists: true },
22+
featured: true,
23+
};
1524
const assistants = await collections.assistants
16-
.find({ userCount: { $gt: 1 }, modelId: modelId ?? { $exists: true }, featured: true })
25+
.find(filter)
26+
.skip(NUM_PER_PAGE * pageIndex)
1727
.sort({ userCount: -1 })
18-
.limit(10)
28+
.limit(NUM_PER_PAGE)
1929
.toArray();
2030

21-
return { assistants: JSON.parse(JSON.stringify(assistants)) as Array<Assistant> };
31+
const numTotalItems = await collections.assistants.countDocuments(filter);
32+
33+
return {
34+
assistants: JSON.parse(JSON.stringify(assistants)) as Array<Assistant>,
35+
numTotalItems,
36+
numItemsPerPage: NUM_PER_PAGE,
37+
};
2238
};

src/routes/assistants/+page.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
1111
import CarbonAdd from "~icons/carbon/add";
1212
import CarbonHelpFilled from "~icons/carbon/help-filled";
13+
import Pagination from "$lib/components/Pagination.svelte";
1314
1415
export let data: PageData;
1516
@@ -124,5 +125,10 @@
124125
No assistants found
125126
{/each}
126127
</div>
128+
<Pagination
129+
classNames="w-full flex justify-center mt-14 mb-4"
130+
numItemsPerPage={data.numItemsPerPage}
131+
numTotalItems={data.numTotalItems}
132+
/>
127133
</div>
128134
</div>

0 commit comments

Comments
 (0)