From 9cd0982be057e537077e868db2ca8a755e54b7a0 Mon Sep 17 00:00:00 2001 From: bernard-ng Date: Wed, 3 Dec 2025 22:51:38 +0200 Subject: [PATCH] feat: classify on article creation --- .../src/components/categories-carousel.tsx | 37 ++++++++++--------- packages/db/src/queries/articles.ts | 11 ++++-- .../db/src/services/category-classifier.ts | 2 +- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/apps/dashboard/src/components/categories-carousel.tsx b/apps/dashboard/src/components/categories-carousel.tsx index b655211..b3653d7 100644 --- a/apps/dashboard/src/components/categories-carousel.tsx +++ b/apps/dashboard/src/components/categories-carousel.tsx @@ -12,6 +12,7 @@ import { cn } from "@basango/ui/lib/utils"; import { useQuery } from "@tanstack/react-query"; import * as React from "react"; +import { Show } from "#dashboard/components/shell/show"; import { useTRPC } from "#dashboard/trpc/client"; type Props = { @@ -25,7 +26,6 @@ export function CategoriesCarousel({ onSelect, selectedCategory }: Props) { const trpc = useTRPC(); const { data, isLoading } = useQuery(trpc.categories.list.queryOptions()); const categories = data ?? []; - const showSkeletons = isLoading && categories.length === 0; return (
@@ -43,22 +43,25 @@ export function CategoriesCarousel({ onSelect, selectedCategory }: Props) { All - {showSkeletons - ? Array.from({ length: PLACEHOLDER_COUNT }).map((_, index) => ( - - - - )) - : categories.map((category) => ( - - onSelect(category.id)} - > - {category.name} - - - ))} + ( + + + + ))} + when={isLoading && categories.length > 0} + > + {categories.map((category) => ( + + onSelect(category.id)} + > + {category.name} + + + ))} + diff --git a/packages/db/src/queries/articles.ts b/packages/db/src/queries/articles.ts index 6f1af10..bcc95cb 100644 --- a/packages/db/src/queries/articles.ts +++ b/packages/db/src/queries/articles.ts @@ -17,6 +17,7 @@ import * as uuid from "uuid"; import { Database } from "#db/client"; import { getSourceIdByName } from "#db/queries/sources"; import { articles, categories, sources } from "#db/schema"; +import { classifyCategory } from "#db/services/category-classifier"; import { CreateArticleParams, GetArticlesParams } from "#db/types/articles"; import { GetDistributionsParams, GetPublicationsParams } from "#db/types/shared"; import { @@ -41,24 +42,26 @@ export async function createArticle(db: Database, params: CreateArticleParams) { }; } - const categoryList = params.categories ?? []; const data = { ...params, - categories: categoryList, + categories: params.categories ?? [], hash: md5(params.link), + id: uuid.v7(), readingTime: computeReadingTime(params.body), sentiment: (params.sentiment ?? "neutral") as Sentiment, sourceId: await getSourceIdByName(db, params.sourceId), tokenStatistics: computeTokenStatistics({ body: params.body, - categories: categoryList, + categories: params.categories ?? [], title: params.title, }), }; + data.categoryId = classifyCategory(data).category.id; + const [result] = await db .insert(articles) - .values({ id: uuid.v7(), ...data }) + .values({ ...data }) .returning({ id: articles.id, sourceId: articles.sourceId, diff --git a/packages/db/src/services/category-classifier.ts b/packages/db/src/services/category-classifier.ts index 819ce3e..fac6c6e 100644 --- a/packages/db/src/services/category-classifier.ts +++ b/packages/db/src/services/category-classifier.ts @@ -124,7 +124,7 @@ export class CategoryClassifier { } } -function classifyCategory(article: ArticleCategories): CategoryScore { +export function classifyCategory(article: ArticleCategories): CategoryScore { const rawCategories = article.categories ?? []; const normalizedCategories = Array.from( new Set(