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
};
};