diff --git a/src/lib/components/archiveProject.svelte b/src/lib/components/archiveProject.svelte index c7896c9912..d7c5b6a1b6 100644 --- a/src/lib/components/archiveProject.svelte +++ b/src/lib/components/archiveProject.svelte @@ -1,4 +1,5 @@ {#if projectsToArchive.length > 0}
- + These projects have been archived and are read-only. You can view and migrate their data.
- + {#each projectsToArchive as project} {@const platforms = filterPlatforms( project.platforms.map((platform) => getPlatformInfo(platform.type)) @@ -292,7 +303,7 @@ {/each} - {#if platforms.length > 3} + {#if platforms.length > 2} {/each} + +
@@ -381,4 +401,7 @@ align-items: center; gap: 8px; } + :global(.pagination-container) { + margin-top: 16px; + } diff --git a/src/lib/components/limit.svelte b/src/lib/components/limit.svelte index c8e72a4012..8a7c1ef672 100644 --- a/src/lib/components/limit.svelte +++ b/src/lib/components/limit.svelte @@ -8,6 +8,8 @@ export let sum: number; export let limit: number; export let name: string; + export let pageParam: string = 'page'; + export let removeOnFirstPage: boolean = false; const options = [ { label: '6', value: 6 }, @@ -23,10 +25,15 @@ url.searchParams.set('limit', limit.toString()); await preferences.setLimit(limit); - if (url.searchParams.has('page')) { - const page = Number(url.searchParams.get('page')); + if (url.searchParams.has(pageParam)) { + const page = Number(url.searchParams.get(pageParam)); const newPage = Math.floor(((page - 1) * previousLimit) / limit); - url.searchParams.set('page', newPage.toString()); + const safePage = Math.max(1, Number.isFinite(newPage) ? newPage : 1); + if (removeOnFirstPage && safePage === 1) { + url.searchParams.delete(pageParam); + } else { + url.searchParams.set(pageParam, safePage.toString()); + } } await goto(url.toString()); diff --git a/src/lib/components/pagination.svelte b/src/lib/components/pagination.svelte index f272f7f66c..975e4cf6e8 100644 --- a/src/lib/components/pagination.svelte +++ b/src/lib/components/pagination.svelte @@ -6,15 +6,21 @@ export let limit: number; export let offset: number; export let useCreateLink = true; + export let pageParam: string = 'page'; + export let removeOnFirstPage: boolean = false; $: currentPage = Math.floor(offset / limit + 1); function getLink(page: number): string { const url = new URL(pageStore.url); if (page === 1) { - url.searchParams.delete('page'); + if (removeOnFirstPage) { + url.searchParams.delete(pageParam); + } else { + url.searchParams.set(pageParam, '1'); + } } else { - url.searchParams.set('page', page.toString()); + url.searchParams.set(pageParam, page.toString()); } return url.toString(); diff --git a/src/lib/components/paginationWithLimit.svelte b/src/lib/components/paginationWithLimit.svelte index 7cf78f6b56..b48fbc0f63 100644 --- a/src/lib/components/paginationWithLimit.svelte +++ b/src/lib/components/paginationWithLimit.svelte @@ -8,13 +8,19 @@ offset, total, name, - useCreateLink = true + useCreateLink = true, + pageParam = 'page', + removeOnFirstPage = false, + ...restProps }: { limit: number; offset: number; total: number; name: string; useCreateLink?: boolean; + pageParam?: string; + removeOnFirstPage?: boolean; + [key: string]: unknown; } = $props(); const showLimit = $derived(!!useCreateLink); @@ -22,10 +28,17 @@ const alignItems = $derived(showLimit ? 'center' : 'flex-end'); - + {#if showLimit} - + {/if} - + diff --git a/src/lib/components/paginator.svelte b/src/lib/components/paginator.svelte index ae8aaf9c43..053e2ea144 100644 --- a/src/lib/components/paginator.svelte +++ b/src/lib/components/paginator.svelte @@ -13,7 +13,8 @@ name = 'items', gap = 's', offset = $bindable(0), - children + children, + ...restProps }: { items: T[]; limit?: number; @@ -26,6 +27,7 @@ | undefined; offset?: number; children: Snippet<[T[], number]>; + [key: string]: unknown; } = $props(); let total = $derived(items.length); @@ -33,7 +35,7 @@ let paginatedItems = $derived(items.slice(offset, offset + limit)); - + {@render children(paginatedItems, limit)} {#if !hideFooter} diff --git a/src/routes/(console)/organization-[organization]/+page.svelte b/src/routes/(console)/organization-[organization]/+page.svelte index 69a84cd8a5..9fb5468371 100644 --- a/src/routes/(console)/organization-[organization]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/+page.svelte @@ -109,11 +109,19 @@ return project.status === 'archived'; } - $: projectsToArchive = isCloud - ? data.projects.projects.filter((project) => project.status === 'archived') - : []; + $: projectsToArchive = (data.archivedProjectsPage ?? data.projects.projects).filter( + (project) => project.status === 'archived' + ); - $: activeProjects = data.projects.projects.filter((project) => project.status !== 'archived'); + $: activeProjects = (data.activeProjectsPage ?? data.projects.projects).filter( + (project) => project.status === 'active' + ); + + $: activeTotalOverall = + data?.activeTotalOverall ?? + data?.organization?.projects?.length ?? + data?.projects?.total ?? + 0; function clearSearch() { searchQuery?.clearInput(); } @@ -165,7 +173,7 @@ {#if activeProjects.length > 0} {#each activeProjects as project} @@ -250,13 +258,16 @@ name="Projects" limit={data.limit} offset={data.offset} - total={data.projects.total} /> + total={activeTotalOverall} /> + currentPlan={$currentPlan} + archivedTotalOverall={data.archivedTotalOverall} + archivedOffset={data.archivedOffset} + limit={data.limit} /> diff --git a/src/routes/(console)/organization-[organization]/+page.ts b/src/routes/(console)/organization-[organization]/+page.ts index e361aeffab..f4a520b5c8 100644 --- a/src/routes/(console)/organization-[organization]/+page.ts +++ b/src/routes/(console)/organization-[organization]/+page.ts @@ -18,25 +18,69 @@ export const load: PageLoad = async ({ params, url, route, depends, parent }) => const offset = pageToOffset(page, limit); const search = getSearch(url); - const projects = await sdk.forConsole.projects.list({ - queries: [ - Query.offset(offset), - Query.equal('teamId', params.organization), - Query.limit(limit), - Query.orderDesc('') - ], - search: search || undefined - }); + const archivedPageRaw = parseInt(url.searchParams.get('archivedPage') || '1', 10); + const archivedPage = + Number.isFinite(archivedPageRaw) && archivedPageRaw > 0 ? archivedPageRaw : 1; + const archivedOffset = pageToOffset(archivedPage, limit); + const [activeProjects, archivedProjects, activeTotal, archivedTotal] = await Promise.all([ + sdk.forConsole.projects.list({ + queries: [ + Query.offset(offset), + Query.equal('teamId', params.organization), + Query.or([Query.equal('status', 'active'), Query.isNull('status')]), + Query.limit(limit), + Query.orderDesc('') + ], + search: search || undefined + }), + sdk.forConsole.projects.list({ + queries: [ + Query.offset(archivedOffset), + Query.equal('teamId', params.organization), + Query.equal('status', 'archived'), + Query.limit(limit), + Query.orderDesc('') + ], + search: search || undefined + }), + sdk.forConsole.projects.list({ + queries: [ + Query.equal('teamId', params.organization), + Query.or([Query.equal('status', 'active'), Query.isNull('status')]) + ], + search: search || undefined + }), + sdk.forConsole.projects.list({ + queries: [ + Query.equal('teamId', params.organization), + Query.equal('status', 'archived') + ], + search: search || undefined + }) + ]); // set `default` if no region! - for (const project of projects.projects) { + for (const project of activeProjects.projects) { + project.region ??= 'default'; + } + for (const project of archivedProjects.projects) { project.region ??= 'default'; } return { offset, limit, - projects, + projects: { + ...activeProjects, + projects: activeProjects.projects, + total: activeTotal.total + }, + activeProjectsPage: activeProjects.projects, + archivedProjectsPage: archivedProjects.projects, + activeTotalOverall: activeTotal.total, + archivedTotalOverall: archivedTotal.total, + archivedOffset, + archivedPage, search }; };