From 9c482e417549a4d26794e64a731a753b8d96594c Mon Sep 17 00:00:00 2001 From: Vadim Malanov Date: Mon, 15 Jun 2026 10:14:10 +0300 Subject: [PATCH] ci: clear remaining GitHub annotations --- .github/workflows/ci.yml | 3 ++ frontend/src/app/RouteFallback.tsx | 16 ++++++++ frontend/src/app/router.tsx | 17 +------- frontend/src/components/common/StatusChip.tsx | 25 +----------- frontend/src/components/common/statusTone.ts | 21 ++++++++++ frontend/src/components/ui/button.tsx | 40 +------------------ frontend/src/components/ui/buttonVariants.ts | 37 +++++++++++++++++ frontend/src/pages/DocumentsPage.tsx | 5 ++- frontend/src/pages/IngestionJobsPage.tsx | 3 +- frontend/src/pages/SearchPage.tsx | 8 ++-- frontend/src/widgets/RecentRunsWidget.tsx | 3 +- 11 files changed, 93 insertions(+), 85 deletions(-) create mode 100644 frontend/src/app/RouteFallback.tsx create mode 100644 frontend/src/components/common/statusTone.ts create mode 100644 frontend/src/components/ui/buttonVariants.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dce930..e5b690c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [main] +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" + jobs: backend: name: Backend (lint + tests + compose) diff --git a/frontend/src/app/RouteFallback.tsx b/frontend/src/app/RouteFallback.tsx new file mode 100644 index 0000000..8d1142a --- /dev/null +++ b/frontend/src/app/RouteFallback.tsx @@ -0,0 +1,16 @@ +import { Skeleton } from "@/components/ui/skeleton"; + +export function RouteFallback() { + return ( +
+ + +
+ {Array.from({ length: 4 }).map((_, i) => ( + + ))} +
+ +
+ ); +} diff --git a/frontend/src/app/router.tsx b/frontend/src/app/router.tsx index e3f0158..c25e711 100644 --- a/frontend/src/app/router.tsx +++ b/frontend/src/app/router.tsx @@ -2,7 +2,7 @@ import { lazy, Suspense } from "react"; import { createBrowserRouter, Navigate } from "react-router-dom"; import { AppShell } from "@/layouts/AppShell"; -import { Skeleton } from "@/components/ui/skeleton"; +import { RouteFallback } from "@/app/RouteFallback"; // Each page is split into its own chunk so the initial bundle only ships the // app shell + the page the user actually opens. Named exports are remapped to @@ -35,21 +35,6 @@ const SettingsPage = lazy(() => import("@/pages/SettingsPage").then((m) => ({ default: m.SettingsPage })) ); -function RouteFallback() { - return ( -
- - -
- {Array.from({ length: 4 }).map((_, i) => ( - - ))} -
- -
- ); -} - function withSuspense(node: React.ReactNode) { return }>{node}; } diff --git a/frontend/src/components/common/StatusChip.tsx b/frontend/src/components/common/StatusChip.tsx index 4aa35aa..d5a2f6b 100644 --- a/frontend/src/components/common/StatusChip.tsx +++ b/frontend/src/components/common/StatusChip.tsx @@ -1,14 +1,5 @@ import { cn } from "@/lib/utils"; - -const TONE: Record = { - ok: { dot: "bg-success", text: "text-success", bg: "bg-success/10" }, - active: { dot: "bg-primary", text: "text-primary-700 dark:text-primary-100", bg: "bg-primary/10" }, - warning: { dot: "bg-warning", text: "text-warning", bg: "bg-warning/10" }, - error: { dot: "bg-destructive", text: "text-destructive", bg: "bg-destructive/10" }, - muted: { dot: "bg-muted-foreground", text: "text-muted-foreground", bg: "bg-muted/60" }, -}; - -export type StatusTone = keyof typeof TONE; +import { STATUS_TONE, type StatusTone } from "@/components/common/statusTone"; export function StatusChip({ tone = "muted", @@ -19,7 +10,7 @@ export function StatusChip({ label: string; className?: string; }) { - const t = TONE[tone]; + const t = STATUS_TONE[tone]; return ( ); } - -export function statusToTone(status: string): StatusTone { - const s = status?.toUpperCase(); - if (!s) return "muted"; - if (s.includes("FAILED") || s === "ERROR") return "error"; - if (s === "INDEXING_COMPLETED" || s === "OK") return "ok"; - if (s === "DISCOVERED" || s.endsWith("_STARTED") || s === "PENDING") return "active"; - if (s === "OCR_COMPLETED" || s === "EXTRACTION_COMPLETED" || s === "CHUNKING_COMPLETED") - return "active"; - if (s === "DEGRADED") return "warning"; - return "muted"; -} diff --git a/frontend/src/components/common/statusTone.ts b/frontend/src/components/common/statusTone.ts new file mode 100644 index 0000000..49b0810 --- /dev/null +++ b/frontend/src/components/common/statusTone.ts @@ -0,0 +1,21 @@ +export const STATUS_TONE = { + ok: { dot: "bg-success", text: "text-success", bg: "bg-success/10" }, + active: { dot: "bg-primary", text: "text-primary-700 dark:text-primary-100", bg: "bg-primary/10" }, + warning: { dot: "bg-warning", text: "text-warning", bg: "bg-warning/10" }, + error: { dot: "bg-destructive", text: "text-destructive", bg: "bg-destructive/10" }, + muted: { dot: "bg-muted-foreground", text: "text-muted-foreground", bg: "bg-muted/60" }, +} as const; + +export type StatusTone = keyof typeof STATUS_TONE; + +export function statusToTone(status: string): StatusTone { + const s = status?.toUpperCase(); + if (!s) return "muted"; + if (s.includes("FAILED") || s === "ERROR") return "error"; + if (s === "INDEXING_COMPLETED" || s === "OK") return "ok"; + if (s === "DISCOVERED" || s.endsWith("_STARTED") || s === "PENDING") return "active"; + if (s === "OCR_COMPLETED" || s === "EXTRACTION_COMPLETED" || s === "CHUNKING_COMPLETED") + return "active"; + if (s === "DEGRADED") return "warning"; + return "muted"; +} diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx index a06125a..2016909 100644 --- a/frontend/src/components/ui/button.tsx +++ b/frontend/src/components/ui/button.tsx @@ -1,45 +1,11 @@ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; - -const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium ring-focus transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", - { - variants: { - variant: { - default: - "bg-primary text-primary-foreground shadow-soft hover:bg-primary-700 active:translate-y-[0.5px]", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border/70", - outline: - "border border-border bg-transparent hover:bg-muted text-foreground", - ghost: - "hover:bg-muted text-foreground", - subtle: - "bg-accent text-accent-foreground hover:bg-accent/70", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - sm: "h-8 px-3 text-xs", - default: "h-9 px-4", - lg: "h-11 px-6 text-base rounded-xl", - icon: "h-9 w-9", - "icon-sm": "h-8 w-8", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -); +import { buttonVariants, type ButtonVariantProps } from "@/components/ui/buttonVariants"; export interface ButtonProps extends React.ButtonHTMLAttributes, - VariantProps { + ButtonVariantProps { asChild?: boolean; } @@ -52,5 +18,3 @@ export const Button = React.forwardRef( } ); Button.displayName = "Button"; - -export { buttonVariants }; diff --git a/frontend/src/components/ui/buttonVariants.ts b/frontend/src/components/ui/buttonVariants.ts new file mode 100644 index 0000000..b40a38b --- /dev/null +++ b/frontend/src/components/ui/buttonVariants.ts @@ -0,0 +1,37 @@ +import { cva, type VariantProps } from "class-variance-authority"; + +export const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium ring-focus transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow-soft hover:bg-primary-700 active:translate-y-[0.5px]", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-border/70", + outline: + "border border-border bg-transparent hover:bg-muted text-foreground", + ghost: + "hover:bg-muted text-foreground", + subtle: + "bg-accent text-accent-foreground hover:bg-accent/70", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + sm: "h-8 px-3 text-xs", + default: "h-9 px-4", + lg: "h-11 px-6 text-base rounded-xl", + icon: "h-9 w-9", + "icon-sm": "h-8 w-8", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); + +export type ButtonVariantProps = VariantProps; diff --git a/frontend/src/pages/DocumentsPage.tsx b/frontend/src/pages/DocumentsPage.tsx index 54e3aa1..0a42abb 100644 --- a/frontend/src/pages/DocumentsPage.tsx +++ b/frontend/src/pages/DocumentsPage.tsx @@ -10,7 +10,8 @@ import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { ConfidenceMeter } from "@/components/common/ConfidenceMeter"; -import { StatusChip, statusToTone } from "@/components/common/StatusChip"; +import { StatusChip } from "@/components/common/StatusChip"; +import { statusToTone } from "@/components/common/statusTone"; import { QualityFlags } from "@/components/common/QualityFlag"; import { EmptyState } from "@/components/common/EmptyState"; import { useDocuments } from "@/hooks/useDocuments"; @@ -31,7 +32,7 @@ export function DocumentsPage() { page_size: 200, }); - const items = data?.items ?? []; + const items = useMemo(() => data?.items ?? [], [data?.items]); const parentRef = useRef(null); const rowVirtualizer = useVirtualizer({ diff --git a/frontend/src/pages/IngestionJobsPage.tsx b/frontend/src/pages/IngestionJobsPage.tsx index 93d5f28..9f18629 100644 --- a/frontend/src/pages/IngestionJobsPage.tsx +++ b/frontend/src/pages/IngestionJobsPage.tsx @@ -7,7 +7,8 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; -import { StatusChip, statusToTone } from "@/components/common/StatusChip"; +import { StatusChip } from "@/components/common/StatusChip"; +import { statusToTone } from "@/components/common/statusTone"; import { Progress } from "@/components/ui/progress"; import { formatNumber, relativeTime } from "@/lib/utils"; import { useIngestionRuns, useStartIngestion } from "@/hooks/useIngestion"; diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index 328cbe9..c9f6733 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -1,9 +1,9 @@ import { useEffect, useMemo, useState } from "react"; -import { AnimatePresence, motion } from "framer-motion"; +import { AnimatePresence } from "framer-motion"; import { ArrowRight, Filter, Loader2, Search as SearchIcon, Sparkles, X } from "lucide-react"; import { PageHeader } from "@/components/common/PageHeader"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Card, CardContent } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; @@ -26,7 +26,7 @@ import type { SearchMode } from "@/services/types"; import { cn, formatNumber } from "@/lib/utils"; export function SearchPage() { - const { query, mode, filters, setQuery, setMode, setFilters, pushHistory, history } = useSearchStore(); + const { query, mode, filters, setQuery, setMode, pushHistory, history } = useSearchStore(); const [draft, setDraft] = useState(query); const [activeId, setActiveId] = useState(null); const debounced = useDebounce(draft, 320); @@ -44,7 +44,7 @@ export function SearchPage() { enabled: query.trim().length > 0, }); - const results = data?.results ?? []; + const results = useMemo(() => data?.results ?? [], [data?.results]); const active = useMemo( () => results.find((r) => r.chunk_id === activeId) ?? results[0] ?? null, [results, activeId] diff --git a/frontend/src/widgets/RecentRunsWidget.tsx b/frontend/src/widgets/RecentRunsWidget.tsx index eedf699..cf469b1 100644 --- a/frontend/src/widgets/RecentRunsWidget.tsx +++ b/frontend/src/widgets/RecentRunsWidget.tsx @@ -1,5 +1,6 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { StatusChip, statusToTone } from "@/components/common/StatusChip"; +import { StatusChip } from "@/components/common/StatusChip"; +import { statusToTone } from "@/components/common/statusTone"; import { useIngestionRuns } from "@/hooks/useIngestion"; import { formatNumber, relativeTime } from "@/lib/utils"; import { Skeleton } from "@/components/ui/skeleton";