From 2927d9980b1f6212e544cb715fc97b52ae2c4bef Mon Sep 17 00:00:00 2001 From: giancarlo Date: Mon, 15 Apr 2024 16:02:14 +0800 Subject: [PATCH] Add sorting options to blog page and CMS clients This update enables sorting of blog page entries based on 'publishedAt' date or custom order. This flexibility has been implemented across the marketing blog page, Keystatic, Wordpress, and Core CMS client services. This functionality allows more control over the presentation of entries. --- apps/web/app/(marketing)/blog/page.tsx | 2 + packages/cms/core/src/cms-client.ts | 2 + packages/cms/keystatic/src/client.ts | 64 +++++++++++++++++-------- packages/cms/wordpress/src/wp-client.ts | 8 ++++ 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/apps/web/app/(marketing)/blog/page.tsx b/apps/web/app/(marketing)/blog/page.tsx index 7925a51d4..86df0eb59 100644 --- a/apps/web/app/(marketing)/blog/page.tsx +++ b/apps/web/app/(marketing)/blog/page.tsx @@ -31,6 +31,8 @@ async function BlogPage({ searchParams }: { searchParams: { page: string } }) { limit, offset, language, + sortBy: 'publishedAt', + sortDirection: 'desc', }); return ( diff --git a/packages/cms/core/src/cms-client.ts b/packages/cms/core/src/cms-client.ts index 2dfb8dee2..7d15732b2 100644 --- a/packages/cms/core/src/cms-client.ts +++ b/packages/cms/core/src/cms-client.ts @@ -36,6 +36,8 @@ export namespace Cms { tags?: string[]; parentIds?: string[]; language?: string | undefined; + sortDirection?: 'asc' | 'desc'; + sortBy?: 'publishedAt' | 'order'; } export interface GetCategoriesOptions { diff --git a/packages/cms/keystatic/src/client.ts b/packages/cms/keystatic/src/client.ts index be7c3576a..de44cf4ff 100644 --- a/packages/cms/keystatic/src/client.ts +++ b/packages/cms/keystatic/src/client.ts @@ -22,33 +22,55 @@ export class KeystaticClient implements CmsClient { const startOffset = options?.offset ?? 0; const endOffset = startOffset + (options?.limit ?? 10); - const filtered = docs.filter((item) => { - const categoryMatch = options?.categories?.length - ? options.categories.find((category) => - item.entry.categories.includes(category), - ) - : true; + const filtered = docs + .filter((item) => { + const categoryMatch = options?.categories?.length + ? options.categories.find((category) => + item.entry.categories.includes(category), + ) + : true; - if (!categoryMatch) { - return false; - } - - if (options.language) { - if (item.entry.language && item.entry.language !== options.language) { + if (!categoryMatch) { return false; } - } - const tagMatch = options?.tags?.length - ? options.tags.find((tag) => item.entry.tags.includes(tag)) - : true; + if (options.language) { + if (item.entry.language && item.entry.language !== options.language) { + return false; + } + } - if (!tagMatch) { - return false; - } + const tagMatch = options?.tags?.length + ? options.tags.find((tag) => item.entry.tags.includes(tag)) + : true; - return true; - }); + if (!tagMatch) { + return false; + } + + return true; + }) + .sort((a, b) => { + const direction = options.sortDirection ?? 'asc'; + const sortBy = options.sortBy ?? 'publishedAt'; + + const transform = (value: string | number | undefined | null) => { + if (typeof value === 'string') { + return new Date(value).getTime(); + } + + return value ?? 0; + }; + + const left = transform(a.entry[sortBy]); + const right = transform(b.entry[sortBy]); + + if (direction === 'asc') { + return left - right; + } + + return right - left; + }); const items = await Promise.all( filtered.slice(startOffset, endOffset).map(async (item) => { diff --git a/packages/cms/wordpress/src/wp-client.ts b/packages/cms/wordpress/src/wp-client.ts index 30a9bb014..15d6e794c 100644 --- a/packages/cms/wordpress/src/wp-client.ts +++ b/packages/cms/wordpress/src/wp-client.ts @@ -38,6 +38,14 @@ export class WordpressClient implements CmsClient { queryParams.append('offset', options.offset.toString()); } + if (options.sortBy) { + queryParams.append('orderby', options.sortBy); + } + + if (options.sortDirection) { + queryParams.append('order', options.sortDirection); + } + if (options?.categories) { const ids = await this.getCategories({ slugs: options.categories,