Skip to content

Commit c8625b5

Browse files
authored
Merge pull request #2086 from HarshMN2345/Fix-SER-27-Minimalize-requests-ti-listRepo-with-debounce
2 parents eedbe51 + bb950d7 commit c8625b5

File tree

1 file changed

+126
-142
lines changed

1 file changed

+126
-142
lines changed

src/lib/components/git/repositories.svelte

Lines changed: 126 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
import { page } from '$app/state';
2424
import Card from '../card.svelte';
2525
import SkeletonRepoList from './skeletonRepoList.svelte';
26-
import { onMount, untrack } from 'svelte';
26+
import { onMount, untrack, onDestroy } from 'svelte';
27+
import { debounce } from '$lib/helpers/debounce';
2728
2829
let {
2930
action = $bindable('select'),
@@ -52,6 +53,28 @@
5253
loadInstallations();
5354
});
5455
56+
const debouncedLoadRepositories = debounce(
57+
async (installationId: string, searchTerm: string) => {
58+
isLoadingRepositories = true;
59+
try {
60+
await loadRepositories(installationId, searchTerm);
61+
} finally {
62+
isLoadingRepositories = false;
63+
}
64+
},
65+
300
66+
);
67+
68+
$effect(() => {
69+
if (selectedInstallation && search !== undefined) {
70+
debouncedLoadRepositories(selectedInstallation, search);
71+
}
72+
});
73+
74+
onDestroy(() => {
75+
debouncedLoadRepositories.cancel();
76+
});
77+
5578
async function loadInstallations() {
5679
if (installationList) {
5780
if (installationList.installations.length) {
@@ -71,7 +94,7 @@
7194
.vcs.listInstallations();
7295
if (installations.length) {
7396
if (!selectedInstallation) {
74-
untrack(() => (selectedInstallation = installationList.installations[0].$id));
97+
untrack(() => (selectedInstallation = installations[0].$id));
7598
}
7699
installation.set(installations.find((entry) => entry.$id === selectedInstallation));
77100
}
@@ -80,22 +103,6 @@
80103
}
81104
82105
async function loadRepositories(installationId: string, search: string) {
83-
if (
84-
!$repositories ||
85-
$repositories.installationId !== installationId ||
86-
$repositories.search !== search
87-
) {
88-
await fetchRepos(installationId, search);
89-
}
90-
91-
if ($repositories.repositories.length && action === 'select') {
92-
selectedRepository = $repositories.repositories[0].id;
93-
$repository = $repositories.repositories[0];
94-
}
95-
return $repositories.repositories;
96-
}
97-
98-
async function fetchRepos(installationId: string, search: string) {
99106
if (product === 'functions') {
100107
$repositories.repositories = (
101108
(await sdk
@@ -117,9 +124,9 @@
117124
)) as unknown as Models.ProviderRepositoryFrameworkList
118125
).frameworkProviderRepositories;
119126
}
120-
121127
$repositories.search = search;
122128
$repositories.installationId = installationId;
129+
return $repositories.repositories;
123130
}
124131
125132
selectedRepository;
@@ -168,10 +175,7 @@
168175
installationsMap.find((entry) => entry.$id === selectedInstallation)
169176
);
170177

171-
isLoadingRepositories = true;
172-
loadRepositories(selectedInstallation, search).then(() => {
173-
isLoadingRepositories = false;
174-
});
178+
debouncedLoadRepositories.cancel();
175179
}}
176180
bind:value={selectedInstallation} />
177181
<InputSearch
@@ -185,130 +189,110 @@
185189
<!-- manual installation change -->
186190
{#if isLoadingRepositories}
187191
<SkeletonRepoList />
188-
{:else}
189-
{#await loadRepositories(selectedInstallation, search)}
190-
<SkeletonRepoList />
191-
{:then response}
192-
{#if response?.length}
193-
<Paginator items={response} hideFooter={response?.length <= 6} limit={6}>
194-
{#snippet children(
195-
paginatedItems: Models.ProviderRepositoryRuntime[] &
196-
Models.ProviderRepositoryFramework[]
197-
)}
198-
<Table.Root columns={1} let:root>
199-
{#each paginatedItems as repo}
200-
<Table.Row.Base {root}>
201-
<Table.Cell {root}>
192+
{:else if $repositories?.repositories?.length}
193+
<Paginator
194+
items={$repositories.repositories}
195+
hideFooter={$repositories.repositories?.length <= 6}
196+
limit={6}>
197+
{#snippet children(
198+
paginatedItems: Models.ProviderRepositoryRuntime[] &
199+
Models.ProviderRepositoryFramework[]
200+
)}
201+
<Table.Root columns={1} let:root>
202+
{#each paginatedItems as repo}
203+
<Table.Row.Base {root}>
204+
<Table.Cell {root}>
205+
<Layout.Stack direction="row" alignItems="center" gap="s">
206+
{#if action === 'select'}
207+
<input
208+
class="is-small u-margin-inline-end-8"
209+
type="radio"
210+
name="repositories"
211+
bind:group={selectedRepository}
212+
onchange={() => repository.set(repo)}
213+
value={repo.id} />
214+
{/if}
215+
{#if product === 'sites'}
216+
{#if repo?.framework && repo.framework !== 'other'}
217+
<Avatar size="xs" alt={repo.name}>
218+
<SvgIcon
219+
name={getFrameworkIcon(repo.framework)}
220+
iconSize="small" />
221+
</Avatar>
222+
{:else}
223+
<Avatar size="xs" alt={repo.name} empty />
224+
{/if}
225+
{:else}
226+
{@const iconName = repo?.runtime
227+
? repo.runtime.split('-')[0]
228+
: undefined}
229+
<Avatar size="xs" alt={repo.name} empty={!iconName}>
230+
<SvgIcon name={iconName} iconSize="small" />
231+
</Avatar>
232+
{/if}
233+
<Layout.Stack
234+
gap="s"
235+
direction="row"
236+
alignItems="center"
237+
justifyContent="space-between">
202238
<Layout.Stack
203239
direction="row"
204-
alignItems="center"
205-
gap="s">
206-
{#if action === 'select'}
207-
<input
208-
class="is-small u-margin-inline-end-8"
209-
type="radio"
210-
name="repositories"
211-
bind:group={selectedRepository}
212-
onchange={() => repository.set(repo)}
213-
value={repo.id} />
214-
{/if}
215-
{#if product === 'sites'}
216-
{#if repo?.framework && repo.framework !== 'other'}
217-
<Avatar size="xs" alt={repo.name}>
218-
<SvgIcon
219-
name={getFrameworkIcon(
220-
repo.framework
221-
)}
222-
iconSize="small" />
223-
</Avatar>
224-
{:else}
225-
<Avatar
226-
size="xs"
227-
alt={repo.name}
228-
empty />
229-
{/if}
230-
{:else}
231-
{@const iconName = repo?.runtime
232-
? repo.runtime.split('-')[0]
233-
: undefined}
234-
<Avatar
235-
size="xs"
236-
alt={repo.name}
237-
empty={!iconName}>
238-
<SvgIcon
239-
name={iconName}
240-
iconSize="small" />
241-
</Avatar>
240+
gap="s"
241+
alignItems="center">
242+
<Typography.Text
243+
truncate
244+
color="--fgcolor-neutral-secondary">
245+
{repo.name}
246+
</Typography.Text>
247+
{#if repo.private}
248+
<Icon
249+
size="s"
250+
icon={IconLockClosed}
251+
color="--fgcolor-neutral-tertiary" />
242252
{/if}
243-
<Layout.Stack
244-
gap="s"
245-
direction="row"
246-
alignItems="center"
247-
justifyContent="space-between">
248-
<Layout.Stack
249-
direction="row"
250-
gap="s"
251-
alignItems="center">
252-
<Typography.Text
253+
{#if !$isSmallViewport}
254+
<time datetime={repo.pushedAt}>
255+
<Typography.Caption
256+
variant="400"
253257
truncate
254-
color="--fgcolor-neutral-secondary">
255-
{repo.name}
256-
</Typography.Text>
257-
{#if repo.private}
258-
<Icon
259-
size="s"
260-
icon={IconLockClosed}
261-
color="--fgcolor-neutral-tertiary" />
262-
{/if}
263-
{#if !$isSmallViewport}
264-
<time datetime={repo.pushedAt}>
265-
<Typography.Caption
266-
variant="400"
267-
truncate
268-
color="--fgcolor-neutral-tertiary">
269-
{timeFromNow(repo.pushedAt)}
270-
</Typography.Caption>
271-
</time>
272-
{/if}
273-
</Layout.Stack>
274-
{#if action === 'button'}
275-
<PinkButton.Button
276-
size="xs"
277-
variant="secondary"
278-
on:click={() => connect(repo)}>
279-
Connect
280-
</PinkButton.Button>
281-
{/if}
282-
</Layout.Stack>
258+
color="--fgcolor-neutral-tertiary">
259+
{timeFromNow(repo.pushedAt)}
260+
</Typography.Caption>
261+
</time>
262+
{/if}
283263
</Layout.Stack>
284-
</Table.Cell>
285-
</Table.Row.Base>
286-
{/each}
287-
</Table.Root>
288-
{/snippet}
289-
</Paginator>
290-
{:else if search}
291-
<EmptySearch hidePages hidePagination bind:search target="repositories">
292-
<svelte:fragment slot="actions">
293-
{#if search}
294-
<Button secondary on:click={() => (search = '')}>
295-
Clear search
296-
</Button>
297-
{/if}
298-
</svelte:fragment>
299-
</EmptySearch>
300-
{:else}
301-
<Card>
302-
<Layout.Stack alignItems="center" justifyContent="center">
303-
<Typography.Text
304-
variation="m-500"
305-
color="--fgcolor-neutral-tertiary">
306-
No repositories available
307-
</Typography.Text>
308-
</Layout.Stack>
309-
</Card>
310-
{/if}
311-
{/await}
264+
{#if action === 'button'}
265+
<PinkButton.Button
266+
size="xs"
267+
variant="secondary"
268+
on:click={() => connect(repo)}>
269+
Connect
270+
</PinkButton.Button>
271+
{/if}
272+
</Layout.Stack>
273+
</Layout.Stack>
274+
</Table.Cell>
275+
</Table.Row.Base>
276+
{/each}
277+
</Table.Root>
278+
{/snippet}
279+
</Paginator>
280+
{:else if search}
281+
<EmptySearch hidePages hidePagination bind:search target="repositories">
282+
<svelte:fragment slot="actions">
283+
{#if search}
284+
<Button secondary on:click={() => (search = '')}>Clear search</Button>
285+
{/if}
286+
</svelte:fragment>
287+
</EmptySearch>
288+
{:else}
289+
<Card>
290+
<Layout.Stack alignItems="center" justifyContent="center">
291+
<Typography.Text variation="m-500" color="--fgcolor-neutral-tertiary">
292+
No repositories available
293+
</Typography.Text>
294+
</Layout.Stack>
295+
</Card>
312296
{/if}
313297
{/if}
314298
</Layout.Stack>

0 commit comments

Comments
 (0)