From 5257d95559757a978ae47cc9de3353d8001ebfa0 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 28 May 2024 21:29:35 +0800 Subject: [PATCH 1/5] fix: home items order is not accurate --- packages/api/src/jobs/update_home.ts | 3 +- .../api/src/resolvers/function_resolvers.ts | 70 +++++++++++-------- packages/api/src/services/library_item.ts | 21 +++++- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/packages/api/src/jobs/update_home.ts b/packages/api/src/jobs/update_home.ts index d60d4a3e4..f2d6d5e59 100644 --- a/packages/api/src/jobs/update_home.ts +++ b/packages/api/src/jobs/update_home.ts @@ -311,7 +311,8 @@ const mixHomeItems = (rankedHomeItems: Array): Array
=> { const authorCount = batch.filter((i) => i.author === item.author).length const siteCount = batch.filter((i) => i.siteName === item.siteName).length const subscriptionCount = batch.filter( - (i) => i.subscription?.name === item.subscription?.name + (i) => + item.subscription && i.subscription?.name === item.subscription.name ).length return ( diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 6f4e84ee9..6e84fcc50 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -639,7 +639,9 @@ export const functionResolvers = { _: unknown, ctx: WithDataSourcesContext ) { - const libraryItemIds = section.items + const items = section.items + + const libraryItemIds = items .filter((item) => item.type === 'library_item') .map((item) => item.id) const libraryItems = ( @@ -653,10 +655,13 @@ export const functionResolvers = { await ctx.dataLoaders.publicItems.loadMany(publicItemIds) ).filter((publicItem) => !isError(publicItem)) as Array - return libraryItems - .map( - (libraryItem) => - ({ + return items + .map((item) => { + const libraryItem = libraryItems.find( + (libraryItem) => item.id === libraryItem.id + ) + if (libraryItem) { + return { id: libraryItem.id, title: libraryItem.title, author: libraryItem.author, @@ -667,36 +672,43 @@ export const functionResolvers = { canArchive: !libraryItem.archivedAt, canDelete: !libraryItem.deletedAt, canSave: false, + canComment: false, + canShare: true, dir: libraryItem.directionality, previewContent: libraryItem.description, subscription: libraryItem.subscription, siteName: libraryItem.siteName, siteIcon: libraryItem.siteIcon, - } as HomeItem) - ) - .concat( - publicItems.map( - (publicItem) => - ({ - id: publicItem.id, - title: publicItem.title, - author: publicItem.author, - dir: publicItem.dir, - previewContent: publicItem.previewContent, - thumbnail: publicItem.thumbnail, - wordCount: publicItem.wordCount, - date: publicItem.createdAt, - url: publicItem.url, - canArchive: false, - canDelete: false, - canSave: true, - broadcastCount: publicItem.stats.broadcastCount, - likeCount: publicItem.stats.likeCount, - saveCount: publicItem.stats.saveCount, - source: publicItem.source, - } as HomeItem) + } + } + + const publicItem = publicItems.find( + (publicItem) => item.id === publicItem.id ) - ) + if (publicItem) { + return { + id: publicItem.id, + title: publicItem.title, + author: publicItem.author, + dir: publicItem.dir, + previewContent: publicItem.previewContent, + thumbnail: publicItem.thumbnail, + wordCount: publicItem.wordCount, + date: publicItem.createdAt, + url: publicItem.url, + canArchive: false, + canDelete: false, + canSave: true, + canComment: true, + canShare: true, + broadcastCount: publicItem.stats.broadcastCount, + likeCount: publicItem.stats.likeCount, + saveCount: publicItem.stats.saveCount, + source: publicItem.source, + } + } + }) + .filter((item) => !!item) }, }, HomeItem: { diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index b90aa0e80..d242c9f31 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -141,7 +141,26 @@ interface Select { const readingProgressDataSource = new ReadingProgressDataSource() export const batchGetLibraryItems = async (ids: readonly string[]) => { - return findLibraryItemsByIds(ids as string[]) + const items = await findLibraryItemsByIds(ids as string[], undefined, { + select: [ + 'id', + 'title', + 'author', + 'thumbnail', + 'wordCount', + 'savedAt', + 'originalUrl', + 'directionality', + 'description', + 'subscription', + 'siteName', + 'siteIcon', + 'archivedAt', + 'deletedAt', + ], + }) + + return ids.map((id) => items.find((item) => item.id === id) || null) } export const getItemUrl = (id: string) => `${env.client.url}/me/${id}` From 9dff961bba96ae02f23529d63df1b682e1d9ce22 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 28 May 2024 21:44:55 +0800 Subject: [PATCH 2/5] fix null checking --- packages/api/src/resolvers/types.ts | 4 ++-- packages/api/src/services/library_item.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/api/src/resolvers/types.ts b/packages/api/src/resolvers/types.ts index 21b049bae..b296acd4b 100644 --- a/packages/api/src/resolvers/types.ts +++ b/packages/api/src/resolvers/types.ts @@ -55,8 +55,8 @@ export interface RequestContext { highlights: DataLoader recommendations: DataLoader uploadFiles: DataLoader - libraryItems: DataLoader - publicItems: DataLoader + libraryItems: DataLoader + publicItems: DataLoader subscriptions: DataLoader } } diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index d242c9f31..93e24ac3d 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -160,7 +160,7 @@ export const batchGetLibraryItems = async (ids: readonly string[]) => { ], }) - return ids.map((id) => items.find((item) => item.id === id) || null) + return ids.map((id) => items.find((item) => item.id === id) || undefined) } export const getItemUrl = (id: string) => `${env.client.url}/me/${id}` From d04626a02cc4e7ba6aec826c011a7c73df2aac19 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 28 May 2024 21:59:37 +0800 Subject: [PATCH 3/5] add slug --- packages/api/src/generated/graphql.ts | 2 ++ packages/api/src/generated/schema.graphql | 1 + packages/api/src/resolvers/function_resolvers.ts | 1 + packages/api/src/schema.ts | 1 + packages/api/src/services/library_item.ts | 1 + 5 files changed, 6 insertions(+) diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index ee60e84b9..47122a25a 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -1303,6 +1303,7 @@ export type HomeItem = { previewContent?: Maybe; saveCount?: Maybe; seen_at?: Maybe; + slug: Scalars['String']; source?: Maybe; thumbnail?: Maybe; title: Scalars['String']; @@ -6043,6 +6044,7 @@ export type HomeItemResolvers, ParentType, ContextType>; saveCount?: Resolver, ParentType, ContextType>; seen_at?: Resolver, ParentType, ContextType>; + slug?: Resolver; source?: Resolver, ParentType, ContextType>; thumbnail?: Resolver, ParentType, ContextType>; title?: Resolver; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 220808a8a..74852616d 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1172,6 +1172,7 @@ type HomeItem { previewContent: String saveCount: Int seen_at: Date + slug: String! source: HomeItemSource thumbnail: String title: String! diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 6e84fcc50..e79c60d48 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -679,6 +679,7 @@ export const functionResolvers = { subscription: libraryItem.subscription, siteName: libraryItem.siteName, siteIcon: libraryItem.siteIcon, + slug: libraryItem.slug, } } diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index 963adf81f..c0067b88f 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -3126,6 +3126,7 @@ const schema = gql` likeCount: Int broadcastCount: Int date: Date! + slug: String! author: String dir: String seen_at: Date diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index 93e24ac3d..80848fc75 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -157,6 +157,7 @@ export const batchGetLibraryItems = async (ids: readonly string[]) => { 'siteIcon', 'archivedAt', 'deletedAt', + 'slug', ], }) From 3b69f0ce0c16996dcca2637774441d176d26ff74 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 29 May 2024 09:15:15 +0800 Subject: [PATCH 4/5] make slug optional --- packages/api/src/generated/graphql.ts | 4 ++-- packages/api/src/generated/schema.graphql | 2 +- packages/api/src/schema.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 47122a25a..63d4e2b14 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -1303,7 +1303,7 @@ export type HomeItem = { previewContent?: Maybe; saveCount?: Maybe; seen_at?: Maybe; - slug: Scalars['String']; + slug?: Maybe; source?: Maybe; thumbnail?: Maybe; title: Scalars['String']; @@ -6044,7 +6044,7 @@ export type HomeItemResolvers, ParentType, ContextType>; saveCount?: Resolver, ParentType, ContextType>; seen_at?: Resolver, ParentType, ContextType>; - slug?: Resolver; + slug?: Resolver, ParentType, ContextType>; source?: Resolver, ParentType, ContextType>; thumbnail?: Resolver, ParentType, ContextType>; title?: Resolver; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 74852616d..c60a0689c 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1172,7 +1172,7 @@ type HomeItem { previewContent: String saveCount: Int seen_at: Date - slug: String! + slug: String source: HomeItemSource thumbnail: String title: String! diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index c0067b88f..c478014e8 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -3126,7 +3126,7 @@ const schema = gql` likeCount: Int broadcastCount: Int date: Date! - slug: String! + slug: String author: String dir: String seen_at: Date From 7a34a03bddc59d53e91bd4705e43cbaef601bb83 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 29 May 2024 11:30:19 +0800 Subject: [PATCH 5/5] fix subscription and public item orders too --- packages/api/src/apollo.ts | 4 +- .../api/src/resolvers/function_resolvers.ts | 12 ++++ packages/api/src/resolvers/types.ts | 2 +- packages/api/src/services/home.ts | 63 +------------------ packages/api/src/services/subscriptions.ts | 11 ++++ 5 files changed, 28 insertions(+), 64 deletions(-) diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts index 67eb0b65a..9c0ce1271 100644 --- a/packages/api/src/apollo.ts +++ b/packages/api/src/apollo.ts @@ -40,7 +40,7 @@ import { countDailyServiceUsage, createServiceUsage, } from './services/service_usage' -import { findSubscriptionsByNames } from './services/subscriptions' +import { batchGetSubscriptionsByNames } from './services/subscriptions' import { batchGetUploadFilesByIds } from './services/upload_file' import { tracer } from './tracing' import { getClaimsByToken, setAuthInCookie } from './utils/auth' @@ -122,7 +122,7 @@ const contextFunc: ContextFunction = async ({ throw new Error('No user id found in claims') } - return findSubscriptionsByNames(claims?.uid || '', names as string[]) + return batchGetSubscriptionsByNames(claims.uid, names as string[]) }), }, } diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index e79c60d48..d29f6229e 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -640,13 +640,16 @@ export const functionResolvers = { ctx: WithDataSourcesContext ) { const items = section.items + console.log('items', items) const libraryItemIds = items .filter((item) => item.type === 'library_item') .map((item) => item.id) + console.log('libraryItemIds', libraryItemIds) const libraryItems = ( await ctx.dataLoaders.libraryItems.loadMany(libraryItemIds) ).filter((libraryItem) => !isError(libraryItem)) as Array + console.log('libraryItems', libraryItems) const publicItemIds = section.items .filter((item) => item.type === 'public_item') @@ -657,9 +660,11 @@ export const functionResolvers = { return items .map((item) => { + console.log('item', item) const libraryItem = libraryItems.find( (libraryItem) => item.id === libraryItem.id ) + console.log('libraryItem', libraryItem) if (libraryItem) { return { id: libraryItem.id, @@ -736,6 +741,13 @@ export const functionResolvers = { const subscription = await ctx.dataLoaders.subscriptions.load( item.subscription ) + if (!subscription) { + return { + name: item.siteName, + icon: item.siteIcon, + type: HomeItemSourceType.Library, + } + } return { id: subscription.id, diff --git a/packages/api/src/resolvers/types.ts b/packages/api/src/resolvers/types.ts index b296acd4b..7aaf46322 100644 --- a/packages/api/src/resolvers/types.ts +++ b/packages/api/src/resolvers/types.ts @@ -57,7 +57,7 @@ export interface RequestContext { uploadFiles: DataLoader libraryItems: DataLoader publicItems: DataLoader - subscriptions: DataLoader + subscriptions: DataLoader } } diff --git a/packages/api/src/services/home.ts b/packages/api/src/services/home.ts index c70a98003..b78772377 100644 --- a/packages/api/src/services/home.ts +++ b/packages/api/src/services/home.ts @@ -1,77 +1,18 @@ import { PublicItem } from '../entity/public_item' -import { HomeItem } from '../generated/graphql' import { authTrx } from '../repository' -import { findLibraryItemsByIds } from './library_item' export const batchGetPublicItems = async ( ids: readonly string[] -): Promise> => { - return authTrx(async (tx) => - tx - .getRepository(PublicItem) - .createQueryBuilder('public_item') - .where('public_item.id IN (:...ids)', { ids }) - .getMany() - ) -} - -export const batchGetHomeItems = async ( - ids: readonly string[] -): Promise> => { - const libraryItems = await findLibraryItemsByIds(ids as string[]) - +): Promise> => { const publicItems = await authTrx(async (tx) => tx .getRepository(PublicItem) .createQueryBuilder('public_item') - .innerJoin( - 'public_item_stats', - 'stats', - 'stats.public_item_id = public_item.id' - ) - .innerJoin( - 'public_item_source', - 'source', - 'source.id = public_item.source_id' - ) .where('public_item.id IN (:...ids)', { ids }) .getMany() ) - return ids - .map((id) => { - const libraryItem = libraryItems.find((li) => li.id === id) - if (libraryItem) { - return { - ...libraryItem, - date: libraryItem.savedAt, - url: libraryItem.originalUrl, - canArchive: !libraryItem.archivedAt, - canDelete: !libraryItem.deletedAt, - canSave: false, - dir: libraryItem.directionality, - subscription: null, - previewContent: libraryItem.description, - } as HomeItem - } else { - const publicItem = publicItems.find((pi) => pi.id === id) - return publicItem - ? ({ - ...publicItem, - date: publicItem.createdAt, - url: publicItem.url, - canArchive: false, - canDelete: false, - canSave: true, - broadcastCount: publicItem.stats.broadcastCount, - likeCount: publicItem.stats.likeCount, - saveCount: publicItem.stats.saveCount, - subscription: publicItem.source, - } as HomeItem) - : undefined - } - }) - .filter((item) => item !== undefined) as Array + return ids.map((id) => publicItems.find((pi) => pi.id === id)) } export const findUnseenPublicItems = async ( diff --git a/packages/api/src/services/subscriptions.ts b/packages/api/src/services/subscriptions.ts index 72b0fc9d2..52f4bef50 100644 --- a/packages/api/src/services/subscriptions.ts +++ b/packages/api/src/services/subscriptions.ts @@ -21,6 +21,17 @@ interface SaveSubscriptionInput { export const UNSUBSCRIBE_EMAIL_TEXT = 'This message was automatically generated by Omnivore.' +export const batchGetSubscriptionsByNames = async ( + userId: string, + names: string[] +) => { + const subscriptions = await findSubscriptionsByNames(userId, names) + + return names.map((name) => + subscriptions.find((s) => s?.name === name || s?.url === name) + ) +} + export const parseUnsubscribeMailTo = (unsubscribeMailTo: string) => { const parsed = new URL(`mailto://${unsubscribeMailTo}`) const subject = parsed.searchParams.get('subject') || 'Unsubscribe'