Skip to content

Commit

Permalink
Offset pagination with variables (HoudiniGraphql#553)
Browse files Browse the repository at this point in the history
* fix bug when counting offset page sizes with query variables

* change snapshot used by intergation test

* changeset

* fixed issue refreshing current list
  • Loading branch information
AlecAivazis committed Sep 20, 2022
1 parent e096943 commit 7666734
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/honest-avocados-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini': patch
---

fixed bug when loading offset-based pages driven by query variable
1 change: 1 addition & 0 deletions integration/src/lib/utils/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const routes = {
Pagination_query_forward_cursor: '/pagination/query/forward-cursor',
Pagination_query_backwards_cursor: '/pagination/query/backwards-cursor',
Pagination_query_offset: '/pagination/query/offset',
Pagination_query_offset_variable: '/pagination/query/offset-variable',

Pagination_fragment_forward_cursor: '/pagination/fragment/forward-cursor',
Pagination_fragment_backwards_cursor: '/pagination/fragment/backwards-cursor',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { graphql, type OffsetVariablePaginationQueryStore, CachePolicy } from '$houdini';
const result: OffsetVariablePaginationQueryStore = graphql`
query OffsetVariablePaginationQuery($limit: Int!) {
usersList(limit: $limit, snapshot: "pagination-query-offset-variables") @paginate {
name
}
}
`;
</script>

<div id="result">
{$result.data?.usersList.map((user) => user?.name).join(', ')}
</div>

<button id="next" on:click={() => result.loadNextPage()}>next</button>

<button id="refetch" on:click={() => result.fetch({ policy: CachePolicy.NetworkOnly })}
>refetch</button
>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function OffsetVariablePaginationQueryVariables() {
return {
limit: 2
};
}
30 changes: 30 additions & 0 deletions integration/src/routes/pagination/query/offset-variable/spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect, test } from '@playwright/test';
import { routes } from '../../../../lib/utils/routes.js';
import { expect_1_gql, expectToBe, goto } from '../../../../lib/utils/testsHelper.js';

test.describe('offset paginatedQuery', () => {
test('loadNextPage', async ({ page }) => {
await goto(page, routes.Pagination_query_offset_variable);

await expectToBe(page, 'Bruce Willis, Samuel Jackson');

// wait for the api response
await expect_1_gql(page, 'button[id=next]');

// make sure we got the new content
await expectToBe(page, 'Bruce Willis, Samuel Jackson, Morgan Freeman, Tom Hanks');
});

test('refetch', async ({ page }) => {
await goto(page, routes.Pagination_query_offset_variable);

// wait for the api response
await expect_1_gql(page, 'button[id=next]');

// wait for the api response
const response = await expect_1_gql(page, 'button[id=refetch]');
expect(response).toBe(
'{"data":{"usersList":[{"name":"Bruce Willis","id":"pagination-query-offset-variables:1"},{"name":"Samuel Jackson","id":"pagination-query-offset-variables:2"},{"name":"Morgan Freeman","id":"pagination-query-offset-variables:3"},{"name":"Tom Hanks","id":"pagination-query-offset-variables:4"}]}}'
);
});
});
15 changes: 9 additions & 6 deletions src/runtime/stores/pagination/offset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input>({
getConfig: () => Promise<ConfigFile>
}) {
// we need to track the most recent offset for this handler
let currentOffset =
let getOffset = () =>
(artifact.refetch?.start as number) ||
countPage(artifact.refetch!.path, getValue()) ||
artifact.refetch!.pageSize

let currentOffset = getOffset() ?? 0

return {
loadNextPage: async ({
limit,
Expand All @@ -45,7 +47,9 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input>({
} = {}) => {
const config = await getConfig()

offset ??= currentOffset
// if the offset is zero then we want to count it just to make sure
// hence why (|| and not ??)
offset ??= currentOffset || getOffset()

// build up the variables to pass to the query
const queryVariables: Record<string, any> = {
Expand Down Expand Up @@ -86,7 +90,7 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input>({

// add the page size to the offset so we load the next page next time
const pageSize = queryVariables.limit || artifact.refetch!.pageSize
currentOffset += pageSize
currentOffset = offset + pageSize

// we're not loading any more
setFetching(false)
Expand All @@ -107,16 +111,15 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input>({

// we are updating the current set of items, count the number of items that currently exist
// and ask for the full data set
const count =
countPage(artifact.refetch!.path, getValue()) || artifact.refetch!.pageSize
const count = currentOffset || getOffset()

// build up the variables to pass to the query
const queryVariables: Record<string, any> = {
...extra,
}

// if there are more records than the first page, we need fetch to load everything
if (count > artifact.refetch!.pageSize) {
if (!artifact.refetch!.pageSize || count > artifact.refetch!.pageSize) {
queryVariables.limit = count
}

Expand Down

0 comments on commit 7666734

Please sign in to comment.