mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-03 12:52:39 +02:00
Merge upstream/dev
This commit is contained in:
commit
2d962f6dd2
107 changed files with 15033 additions and 2277 deletions
|
|
@ -137,10 +137,9 @@ function ReportCard({
|
|||
const autoOpenedRef = useRef(false);
|
||||
const [metadata, setMetadata] = useState<{
|
||||
title: string;
|
||||
wordCount: number | null;
|
||||
versionLabel: string | null;
|
||||
content: string | null;
|
||||
}>({ title, wordCount: wordCount ?? null, versionLabel: null, content: null });
|
||||
}>({ title, versionLabel: null, content: null });
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
|
@ -169,10 +168,8 @@ function ReportCard({
|
|||
}
|
||||
}
|
||||
const resolvedTitle = parsed.data.title || title;
|
||||
const resolvedWordCount = parsed.data.report_metadata?.word_count ?? wordCount ?? null;
|
||||
setMetadata({
|
||||
title: resolvedTitle,
|
||||
wordCount: resolvedWordCount,
|
||||
versionLabel,
|
||||
content: parsed.data.content ?? null,
|
||||
});
|
||||
|
|
@ -182,7 +179,7 @@ function ReportCard({
|
|||
openPanel({
|
||||
reportId,
|
||||
title: resolvedTitle,
|
||||
wordCount: resolvedWordCount ?? undefined,
|
||||
wordCount: parsed.data.report_metadata?.word_count ?? wordCount ?? undefined,
|
||||
shareToken,
|
||||
});
|
||||
}
|
||||
|
|
@ -210,7 +207,6 @@ function ReportCard({
|
|||
openPanel({
|
||||
reportId,
|
||||
title: metadata.title,
|
||||
wordCount: metadata.wordCount ?? undefined,
|
||||
shareToken,
|
||||
});
|
||||
};
|
||||
|
|
@ -233,10 +229,8 @@ function ReportCard({
|
|||
<span className="inline-block h-3 w-24 rounded bg-muted/60 animate-pulse" />
|
||||
) : (
|
||||
<>
|
||||
{metadata.wordCount != null && `${metadata.wordCount.toLocaleString()} words`}
|
||||
{metadata.wordCount != null && metadata.versionLabel && (
|
||||
<Dot className="inline size-4" />
|
||||
)}
|
||||
Markdown
|
||||
{metadata.versionLabel && <Dot className="inline size-4" />}
|
||||
{metadata.versionLabel}
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import type { ToolCallMessagePartProps } from "@assistant-ui/react";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import { Dot } from "lucide-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import * as pdfjsLib from "pdfjs-dist";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
|
@ -9,6 +10,7 @@ import { z } from "zod";
|
|||
import { openReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom";
|
||||
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
||||
import { useMediaQuery } from "@/hooks/use-media-query";
|
||||
import { baseApiService } from "@/lib/apis/base-api.service";
|
||||
import { getAuthHeaders } from "@/lib/auth-utils";
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
|
||||
|
|
@ -32,6 +34,18 @@ const GenerateResumeResultSchema = z.object({
|
|||
error: z.string().nullish(),
|
||||
});
|
||||
|
||||
const ResumeVersionsResponseSchema = z.object({
|
||||
id: z.number(),
|
||||
versions: z
|
||||
.array(
|
||||
z.object({
|
||||
id: z.number(),
|
||||
created_at: z.string().nullish(),
|
||||
})
|
||||
)
|
||||
.nullish(),
|
||||
});
|
||||
|
||||
type GenerateResumeArgs = z.infer<typeof GenerateResumeArgsSchema>;
|
||||
type GenerateResumeResult = z.infer<typeof GenerateResumeResultSchema>;
|
||||
|
||||
|
|
@ -201,6 +215,7 @@ function ResumeCard({
|
|||
const autoOpenedRef = useRef(false);
|
||||
const [pdfUrl, setPdfUrl] = useState<string | null>(null);
|
||||
const [thumbState, setThumbState] = useState<"loading" | "ready" | "error">("loading");
|
||||
const [versionLabel, setVersionLabel] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const previewPath = shareToken
|
||||
|
|
@ -219,6 +234,35 @@ function ResumeCard({
|
|||
}
|
||||
}, [reportId, title, shareToken, autoOpen, isDesktop, openPanel]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const fetchVersions = async () => {
|
||||
try {
|
||||
const url = shareToken
|
||||
? `/api/v1/public/${shareToken}/reports/${reportId}/content`
|
||||
: `/api/v1/reports/${reportId}/content`;
|
||||
const rawData = await baseApiService.get<unknown>(url);
|
||||
if (cancelled) return;
|
||||
const parsed = ResumeVersionsResponseSchema.safeParse(rawData);
|
||||
if (parsed.success) {
|
||||
const versions = parsed.data.versions;
|
||||
if (versions && versions.length > 1) {
|
||||
const idx = versions.findIndex((v) => v.id === reportId);
|
||||
if (idx >= 0) {
|
||||
setVersionLabel(`version ${idx + 1}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// silently ignore — version label is non-critical
|
||||
}
|
||||
};
|
||||
fetchVersions();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [reportId, shareToken]);
|
||||
|
||||
const onThumbLoad = useCallback(() => setThumbState("ready"), []);
|
||||
const onThumbError = useCallback(() => setThumbState("error"), []);
|
||||
|
||||
|
|
@ -243,8 +287,12 @@ function ResumeCard({
|
|||
className="w-full text-left transition-colors hover:bg-muted/50 focus:outline-none focus-visible:outline-none cursor-pointer select-none"
|
||||
>
|
||||
<div className="px-5 pt-5 pb-4">
|
||||
<p className="text-base font-semibold text-foreground line-clamp-2">{title}</p>
|
||||
<p className="text-sm text-muted-foreground mt-0.5">PDF</p>
|
||||
<p className="text-sm font-semibold text-foreground line-clamp-2">{title}</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
PDF
|
||||
{versionLabel && <Dot className="inline size-4" />}
|
||||
{versionLabel}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mx-5 h-px bg-border/50" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue