Skip to content

Commit

Permalink
[ALS-7492] Fix loading more values on the add filter page (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesPeck authored Oct 7, 2024
1 parent 94b0bdf commit bf64cd7
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 59 deletions.
62 changes: 42 additions & 20 deletions src/lib/components/OptionsSelectionList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,64 @@
let searchInput: string = '';
export let unselectedOptions: string[] = [];
export let selectedOptions: string[] = [];
export let selectedOptionEndLocation = 20;
export let currentlyLoading: boolean = false;
export let showClearAll: boolean = true;
export let showSelectAll: boolean = true;
export let allOptionsLoaded: boolean = false;
export let allOptions: string[] = [];
export let allOptions: string[] | undefined = undefined;
let currentlyLoadingSelected: boolean = false;
let unselectedOptionsContainer: HTMLElement;
let selectedOptionsContainer: HTMLElement;
let selectedOptionEndLocation = 20;
let allSelectedOptionsLoaded: boolean = false;
const dispatch = createEventDispatcher<{ scroll: { search: string } }>();
function shouldLoadMore(element: HTMLElement) {
$: infiniteScroll = allOptions === undefined;
$: totalAvailableOptions = infiniteScroll
? Infinity
: (allOptions?.length || 0) - selectedOptions.length;
$: allUnselectedOptionsLoaded = infiniteScroll
? allOptionsLoaded
: unselectedOptions.length >= totalAvailableOptions;
$: allSelectedOptionsLoaded = infiniteScroll
? allSelectedOptionsLoaded
: displayedSelectedOptions.length >= selectedOptions.length;
$: displayedSelectedOptions = selectedOptions.slice(0, selectedOptionEndLocation);
function shouldLoadMore(element: HTMLElement, allLoaded: boolean) {
const scrollTop = element.scrollTop;
const containerHeight = element.clientHeight;
const contentHeight = element.scrollHeight;
const scrollBuffer = 30;
const hasLoadedAll = !unselectedOptions || unselectedOptions.length === 0;
return (
hasLoadedAll ||
(!hasLoadedAll && contentHeight - (scrollTop + containerHeight) <= scrollBuffer)
);
return !allLoaded && contentHeight - (scrollTop + containerHeight) <= scrollBuffer;
}
function handleScroll() {
if (!unselectedOptionsContainer) return;
if (!currentlyLoading && shouldLoadMore(unselectedOptionsContainer)) {
if (
!currentlyLoading &&
shouldLoadMore(unselectedOptionsContainer, allUnselectedOptionsLoaded)
) {
dispatch('scroll', { search: searchInput });
}
}
function loadMoreSelectedOptions() {
if (!selectedOptionsContainer) return;
currentlyLoadingSelected = true;
if (shouldLoadMore(selectedOptionsContainer, allSelectedOptionsLoaded)) {
selectedOptionEndLocation = selectedOptionEndLocation + 20;
}
currentlyLoadingSelected = false;
}
function onSearch() {
dispatch('scroll', { search: searchInput });
unselectedOptionsContainer.scrollTop = 0;
Expand All @@ -59,7 +85,7 @@
}
function selectAllOptions() {
if (allOptions.length !== 0) {
if (allOptions && allOptions?.length !== 0) {
selectedOptions = allOptions;
unselectedOptions = [];
selectedOptionEndLocation = 20;
Expand All @@ -70,18 +96,9 @@
}
}
function loadMoreSelectedOptions() {
if (!selectedOptionsContainer) return;
if (shouldLoadMore(selectedOptionsContainer)) {
selectedOptionEndLocation = selectedOptionEndLocation + 20;
}
}
function getID(option: string) {
return option.replaceAll(' ', '-').toLowerCase();
}
$: displayedSelectedOptions = selectedOptions.slice(0, selectedOptionEndLocation);
</script>

<div data-testid="optional-selection-list" class="flex w-full">
Expand Down Expand Up @@ -169,6 +186,11 @@
{option}
</label>
{/each}
{#if currentlyLoadingSelected}
<div class="flex justify-center">
<ProgressRadial width="w-5" meter="stroke-primary-500" track="stroke-primary-500/30" />
</div>
{/if}
</div>
</section>
</div>
Expand Down
22 changes: 11 additions & 11 deletions src/lib/components/explorer/AddFilter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
let pageSize = 20;
let unselectedOptions: string[] = [];
let selectedOptions: string[] = [];
let startLocation = 0;
let startLocation = pageSize;
let lastSearchTerm = '';
let loading = false;
let display: string;
Expand Down Expand Up @@ -110,30 +110,30 @@
loading = true;
try {
let nextOptions = (data?.values || []).filter((option) => !selectedOptions.includes(option));
let endLocation = Math.min(startLocation + pageSize, totalOptions);
let allOptions = data?.values || [];
if (search !== lastSearchTerm || !lastSearchTerm.includes(search)) {
// new search
startLocation = 0;
endLocation = startLocation + pageSize;
unselectedOptions = [];
lastSearchTerm = search;
}
if (search) {
nextOptions = nextOptions.filter((value) =>
value.toLowerCase().includes(search.toLowerCase()),
);
}
let filteredOptions = allOptions.filter(
(option) =>
!selectedOptions.includes(option) &&
(!search || option.toLowerCase().includes(search.toLowerCase())),
);
const endLocation = Math.min(startLocation + pageSize, filteredOptions.length);
const nextOptions = filteredOptions.slice(startLocation, endLocation);
nextOptions = nextOptions.slice(startLocation, endLocation);
unselectedOptions = [...unselectedOptions, ...nextOptions];
startLocation = endLocation;
} catch (error) {
console.error(error);
toastStore.trigger({
message: 'An error occured while loading more options. Please try again later.',
message: 'An error occurred while loading more options. Please try again later.',
background: 'variant-filled-error',
});
}
Expand Down
54 changes: 28 additions & 26 deletions src/lib/components/explorer/genome-filter/gene/Genes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,19 @@
: allGenes.filter((gene) => !$selectedGenes.includes(gene));
let lastFilter = '';
let pageSize = 50;
let pageSize = 20;
let currentPage = 0;
let totalPages = 1;
let loading = false;
let allOptionsLoaded = false;
// given a search term, return new values to be added to displayed options
async function getGeneValues(search: string = '') {
const newSearch = lastFilter !== search;
if (!newSearch && currentPage >= totalPages) return;
if (!newSearch && (currentPage >= totalPages || allOptionsLoaded)) return;
loading = true;
await api
.get(
try {
const response = await api.get(
`picsure/search/${resources.hpds}/values/?` +
new URLSearchParams({
genomicConceptPath: 'Gene_with_variant',
Expand All @@ -39,27 +38,29 @@
size: pageSize.toString(),
}),
{ 'content-type': 'application/json' },
)
.then((response) => {
if (response?.error) {
return Promise.reject(response.error);
}
return response;
})
.then((response) => {
allGenes = newSearch ? response.results : [...allGenes, ...response.results];
totalPages = Math.ceil(response.total / pageSize);
currentPage = response.page;
lastFilter = search;
})
.catch((error) => {
console.error(error);
toastStore.trigger({
message: 'An error occured while loading genes list.',
background: 'variant-filled-error',
});
);
if (response?.error) {
throw response.error;
}
const newGenes = response.results;
allGenes = newSearch ? newGenes : [...allGenes, ...newGenes];
totalPages = Math.ceil(response.total / pageSize);
currentPage = response.page;
lastFilter = search;
// Check if we've loaded all options
allOptionsLoaded = newGenes.length < pageSize;
} catch (error) {
console.error(error);
toastStore.trigger({
message: 'An error occurred while loading genes list.',
background: 'variant-filled-error',
});
loading = false;
} finally {
loading = false;
}
}
onMount(async () => {
Expand All @@ -74,6 +75,7 @@
bind:unselectedOptions={unselectedGenes}
bind:selectedOptions={$selectedGenes}
bind:currentlyLoading={loading}
{allOptionsLoaded}
on:scroll={(event) => getGeneValues(event.detail.search)}
/>
</div>
Loading

0 comments on commit bf64cd7

Please sign in to comment.