Skip to content

Commit ff0c13e

Browse files
authored
chore: add per_page parameter to page (#301)
* chore: add per_page parameter to page Adds per_page parameter to the page. If you pass in ?per_page=4 into the URL, it'll show only the last 4 updated extensions. Open for suggestions on other names for it. Signed-off-by: Charlie Drage <[email protected]> * chore: update to use per_page Signed-off-by: Charlie Drage <[email protected]> --------- Signed-off-by: Charlie Drage <[email protected]>
1 parent 8e0ec26 commit ff0c13e

File tree

2 files changed

+186
-5
lines changed

2 files changed

+186
-5
lines changed

src/lib/ui/ExtensionsList.spec.ts

+137
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,140 @@ test('check categories', async () => {
4949
const category2 = screen.getByText('category2');
5050
expect(category2).toBeInTheDocument();
5151
});
52+
53+
test('if per_page is passed into window.location.search then it should be used to filter extensions', async () => {
54+
// Mock query to be last 1
55+
vi.spyOn(window, 'location', 'get').mockReturnValue({
56+
search: '?per_page=1',
57+
} as unknown as Location);
58+
59+
const extensionsByCategories: ExtensionByCategoryInfo[] = [
60+
{
61+
category: 'category1',
62+
extensions: [
63+
{
64+
displayName: 'dummy1',
65+
versions: [
66+
{
67+
version: '1.0.0',
68+
// Todays date minus 1 day, to make sure it is NOT the most recent one (we want to show dummy2)
69+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 1)),
70+
files: [],
71+
},
72+
],
73+
} as unknown as CatalogExtensionInfo,
74+
],
75+
},
76+
{
77+
category: 'category2',
78+
extensions: [
79+
{
80+
displayName: 'dummy2',
81+
versions: [
82+
{
83+
version: '1.0.0',
84+
lastUpdated: new Date(),
85+
files: [],
86+
},
87+
],
88+
} as unknown as CatalogExtensionInfo,
89+
],
90+
},
91+
];
92+
93+
render(ExtensionsList, { extensionsByCategories });
94+
95+
// Make sure that displayname dummy2 is shown, as it is the "most" up to date one.
96+
const dummy2 = screen.getByText('dummy2');
97+
expect(dummy2).toBeInTheDocument();
98+
99+
// Dummy1 should NOT be shown
100+
const dummy1 = screen.queryByText('dummy1');
101+
expect(dummy1).not.toBeInTheDocument();
102+
103+
// Categories category1 and category2 should be NOT shown
104+
const category1 = screen.queryByText('category1');
105+
expect(category1).not.toBeInTheDocument();
106+
107+
const category2 = screen.queryByText('category2');
108+
expect(category2).not.toBeInTheDocument();
109+
});
110+
111+
test('if per_page is passed in with 4, it should show last 4 extensions even if there is 5 in the list', async () => {
112+
// Mock query to be last 4
113+
vi.spyOn(window, 'location', 'get').mockReturnValue({
114+
search: '?per_page=4',
115+
} as unknown as Location);
116+
117+
const extensionsByCategories: ExtensionByCategoryInfo[] = [
118+
{
119+
category: 'category1',
120+
extensions: [
121+
{
122+
displayName: 'dummy1',
123+
versions: [
124+
{
125+
version: '1.0.0',
126+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 1)),
127+
files: [],
128+
},
129+
],
130+
} as unknown as CatalogExtensionInfo,
131+
{
132+
displayName: 'dummy2',
133+
versions: [
134+
{
135+
version: '1.0.0',
136+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 2)),
137+
files: [],
138+
},
139+
],
140+
} as unknown as CatalogExtensionInfo,
141+
{
142+
displayName: 'dummy3',
143+
versions: [
144+
{
145+
version: '1.0.0',
146+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 3)),
147+
files: [],
148+
},
149+
],
150+
} as unknown as CatalogExtensionInfo,
151+
{
152+
displayName: 'dummy4',
153+
versions: [
154+
{
155+
version: '1.0.0',
156+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 4)),
157+
files: [],
158+
},
159+
],
160+
} as unknown as CatalogExtensionInfo,
161+
{
162+
displayName: 'dummy5',
163+
versions: [
164+
{
165+
version: '1.0.0',
166+
lastUpdated: new Date(new Date().setDate(new Date().getDate() - 5)),
167+
files: [],
168+
},
169+
],
170+
} as unknown as CatalogExtensionInfo,
171+
],
172+
},
173+
];
174+
175+
render(ExtensionsList, { extensionsByCategories });
176+
177+
// Make sure that displayname dummy4 is shown, as it is the "most" up to date one.
178+
const dummy4 = screen.getByText('dummy4');
179+
expect(dummy4).toBeInTheDocument();
180+
181+
// Dummy5 should NOT be shown, as it's the "oldest" one.
182+
const dummy5 = screen.queryByText('dummy5');
183+
expect(dummy5).not.toBeInTheDocument();
184+
185+
// Categories category1 should be NOT shown
186+
const category1 = screen.queryByText('category1');
187+
expect(category1).not.toBeInTheDocument();
188+
});

src/lib/ui/ExtensionsList.svelte

+49-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,57 @@
11
<script lang="ts">
2-
import type { ExtensionByCategoryInfo } from '$lib/api/extensions-info';
2+
import type { CatalogExtensionInfo, ExtensionByCategoryInfo } from '$lib/api/extensions-info';
33
4+
import ExtensionByCategoryCard from './ExtensionByCategoryCard.svelte';
45
import ExtensionsByCategory from './ExtensionsByCategory.svelte';
56
6-
const { extensionsByCategories }: { extensionsByCategories: ExtensionByCategoryInfo[] } = $props();
7+
interface Props {
8+
extensionsByCategories: ExtensionByCategoryInfo[];
9+
}
10+
let { extensionsByCategories }: Props = $props();
11+
12+
let filteredExtensions = $state<CatalogExtensionInfo[]>([]);
13+
let showCategories = $state<boolean>(true);
14+
15+
// Get the per_page from the URL
16+
function getPerPageLimit(): number | undefined {
17+
const perPage = new URLSearchParams(window.location.search).get('per_page');
18+
return perPage ? parseInt(perPage, 10) : undefined;
19+
}
20+
21+
// Sort extensions based upon the last updated date based upon what's in .versions array
22+
function getSortedExtensions(extensions: CatalogExtensionInfo[]): CatalogExtensionInfo[] {
23+
return [...extensions].sort((a, b) => {
24+
const aLastUpdated = a.versions?.[a.versions.length - 1]?.lastUpdated ?? 0;
25+
const bLastUpdated = b.versions?.[b.versions.length - 1]?.lastUpdated ?? 0;
26+
return Number(bLastUpdated) - Number(aLastUpdated);
27+
});
28+
}
29+
30+
$effect(() => {
31+
const limit = getPerPageLimit();
32+
showCategories = !limit;
33+
34+
if (limit) {
35+
const allExtensions = extensionsByCategories.flatMap(({ extensions }) => extensions);
36+
filteredExtensions = getSortedExtensions(allExtensions).slice(0, limit);
37+
}
38+
});
739
</script>
840

941
<div class="flex flex-col h-full">
10-
{#each extensionsByCategories as extensionByCategoryInfo}
11-
<ExtensionsByCategory {extensionByCategoryInfo} />
12-
{/each}
42+
{#if showCategories}
43+
{#each extensionsByCategories as extensionByCategoryInfo}
44+
<ExtensionsByCategory {extensionByCategoryInfo} />
45+
{/each}
46+
{:else}
47+
<div
48+
class="mt-2 grid min-[920px]:grid-cols-2 min-[1180px]:grid-cols-3 gap-3"
49+
role="region"
50+
aria-label="Filtered extensions"
51+
>
52+
{#each filteredExtensions as extension}
53+
<ExtensionByCategoryCard {extension} />
54+
{/each}
55+
</div>
56+
{/if}
1357
</div>

0 commit comments

Comments
 (0)