diff --git a/docs/docs/30-administration/11-forges/30-gitea.md b/docs/docs/30-administration/11-forges/30-gitea.md index bb8e93c2a..23cd6849a 100644 --- a/docs/docs/30-administration/11-forges/30-gitea.md +++ b/docs/docs/30-administration/11-forges/30-gitea.md @@ -48,6 +48,10 @@ For reference see [Configuration Cheat Sheet](https://docs.gitea.io/en-us/config ![gitea oauth setup](gitea_oauth.gif) +:::warning +Make sure your Gitea configuration allows requesting the API with a fixed page length of 50. The default value for the maximum page size is 50, but if you set a value lower than 50, some Woodpecker features will not work properly. Also see the [Configuration Cheat Sheet](https://docs.gitea.com/administration/config-cheat-sheet#api-api). +::: + ## Configuration This is a full list of configuration options. Please note that many of these options use default configuration values that should work for the majority of installations. diff --git a/docs/docs/30-administration/11-forges/35-forgejo.md b/docs/docs/30-administration/11-forges/35-forgejo.md index df7793118..b70c243f0 100644 --- a/docs/docs/30-administration/11-forges/35-forgejo.md +++ b/docs/docs/30-administration/11-forges/35-forgejo.md @@ -50,6 +50,10 @@ For reference see [Configuration Cheat Sheet](https://forgejo.org/docs/latest/ad ![forgejo oauth setup](gitea_oauth.gif) +:::warning +Make sure your Forgejo configuration allows requesting the API with a fixed page length of 50. The default value for the maximum page size is 50, but if you set a value lower than 50, some Woodpecker features will not work properly. Also see the [Configuration Cheat Sheet](https://forgejo.org/docs/latest/admin/config-cheat-sheet/#api-api). +::: + ## Configuration This is a full list of configuration options. Please note that many of these options use default configuration values that should work for the majority of installations. diff --git a/web/src/components/repo/settings/SecretsTab.vue b/web/src/components/repo/settings/SecretsTab.vue index a2c57a35b..d13189a4d 100644 --- a/web/src/components/repo/settings/SecretsTab.vue +++ b/web/src/components/repo/settings/SecretsTab.vue @@ -72,7 +72,6 @@ async function loadSecrets(page: number, level: 'repo' | 'org' | 'global'): Prom const { resetPage, data: _secrets } = usePagination(loadSecrets, () => !selectedSecret.value, { each: ['repo', 'org', 'global'], - pageSize: 50, }); const secrets = computed(() => { const secretsList: Record = {}; diff --git a/web/src/compositions/usePaginate.test.ts b/web/src/compositions/usePaginate.test.ts index 37d603925..c76303069 100644 --- a/web/src/compositions/usePaginate.test.ts +++ b/web/src/compositions/usePaginate.test.ts @@ -48,6 +48,7 @@ describe('usePaginate', () => { usePaginationComposition = usePagination<{ name: string }>( async (page) => repoSecrets[page - 1], () => true, + { pageSize: 3 }, ); }); await waitForState(usePaginationComposition.loading, true); @@ -63,6 +64,7 @@ describe('usePaginate', () => { usePaginationComposition = usePagination<{ name: string }>( async (page) => repoSecrets[page - 1], () => true, + { pageSize: 3 }, ); }); await waitForState(usePaginationComposition.loading, true); @@ -86,7 +88,7 @@ describe('usePaginate', () => { return orgSecrets[page - 1]; }, () => true, - { each: ['repo', 'org'] }, + { each: ['repo', 'org'], pageSize: 3 }, ); }); await waitForState(usePaginationComposition.loading, true); @@ -111,6 +113,7 @@ describe('usePaginate', () => { usePaginationComposition = usePagination<{ name: string }>( async (page) => repoSecrets[page - 1], () => true, + { pageSize: 3 }, ); }); await waitForState(usePaginationComposition.loading, true); @@ -132,6 +135,7 @@ describe('usePaginate', () => { usePaginationComposition = usePagination<{ name: string }>( async (page) => repoSecrets[page - 1], () => true, + { pageSize: 3 }, ); }); await waitForState(usePaginationComposition.loading, true); diff --git a/web/src/compositions/usePaginate.ts b/web/src/compositions/usePaginate.ts index 9bcfdb44c..657f55cd1 100644 --- a/web/src/compositions/usePaginate.ts +++ b/web/src/compositions/usePaginate.ts @@ -1,19 +1,26 @@ import { useInfiniteScroll } from '@vueuse/core'; import { onMounted, ref, watch, type Ref, type UnwrapRef } from 'vue'; -export async function usePaginate(getSingle: (page: number) => Promise): Promise { +const defaultPageSize = 50; + +// usePaginate loads all pages +export async function usePaginate( + getSingle: (page: number) => Promise, + pageSize: number = defaultPageSize, +): Promise { let hasMore = true; let page = 1; const result: T[] = []; while (hasMore) { const singleRes = await getSingle(page); result.push(...singleRes); - hasMore = singleRes.length !== 0; + hasMore = singleRes.length >= pageSize; page += 1; } return result; } +// usePagination loads pages on demand export function usePagination( _loadData: (page: number, arg: S) => Promise, isActive: () => boolean = () => true, @@ -25,7 +32,7 @@ export function usePagination( ) { const scrollElement = _scrollElement === null ? null : ref(document.getElementById('scroll-component')); const page = ref(1); - const pageSize = ref(_pageSize ?? 0); + const pageSize = ref(_pageSize ?? defaultPageSize); const hasMore = ref(true); const data = ref([]) as Ref; const loading = ref(false); @@ -48,14 +55,12 @@ export function usePagination( // use next each element each.value.shift(); page.value = 1; - pageSize.value = _pageSize ?? 0; hasMore.value = each.value.length > 0; if (hasMore.value) { loading.value = false; await loadData(); } } - pageSize.value = newData.length; loading.value = false; } @@ -76,7 +81,6 @@ export function usePagination( const _page = page.value; page.value = 1; - pageSize.value = _pageSize ?? 0; hasMore.value = true; data.value = []; loading.value = false;