Merge remote-tracking branch 'upstream/main' into feat/bookstack-connector

This commit is contained in:
Differ 2025-12-06 09:15:02 +08:00
commit e238fab638
110 changed files with 10076 additions and 1671 deletions

View file

@ -3,7 +3,7 @@
import { useAtomValue } from "jotai";
import { usePathname } from "next/navigation";
import { useTranslations } from "next-intl";
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { activeChatAtom } from "@/atoms/chats/chat-query.atoms";
import {
Breadcrumb,
@ -14,6 +14,7 @@ import {
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { useSearchSpace } from "@/hooks/use-search-space";
import { authenticatedFetch, getBearerToken } from "@/lib/auth-utils";
interface BreadcrumbItemInterface {
label: string;
@ -34,6 +35,36 @@ export function DashboardBreadcrumb() {
autoFetch: !!searchSpaceId,
});
// State to store document title for editor breadcrumb
const [documentTitle, setDocumentTitle] = useState<string | null>(null);
// Fetch document title when on editor page
useEffect(() => {
if (segments[2] === "editor" && segments[3] && searchSpaceId) {
const documentId = segments[3];
const token = getBearerToken();
if (token) {
authenticatedFetch(
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/search-spaces/${searchSpaceId}/documents/${documentId}/editor-content`,
{ method: "GET" }
)
.then((res) => res.json())
.then((data) => {
if (data.title) {
setDocumentTitle(data.title);
}
})
.catch(() => {
// If fetch fails, just use the document ID
setDocumentTitle(null);
});
}
} else {
setDocumentTitle(null);
}
}, [segments, searchSpaceId]);
// Parse the pathname to create breadcrumb items
const generateBreadcrumbs = (path: string): BreadcrumbItemInterface[] => {
const segments = path.split("/").filter(Boolean);
@ -66,6 +97,7 @@ export function DashboardBreadcrumb() {
logs: t("logs"),
chats: t("chats"),
settings: t("settings"),
editor: t("editor"),
};
sectionLabel = sectionLabels[section] || sectionLabel;
@ -73,7 +105,21 @@ export function DashboardBreadcrumb() {
// Handle sub-sections
if (segments[3]) {
const subSection = segments[3];
let subSectionLabel = subSection.charAt(0).toUpperCase() + subSection.slice(1);
// Handle editor sub-sections (document ID)
if (section === "editor") {
const documentLabel = documentTitle || subSection;
breadcrumbs.push({
label: t("documents"),
href: `/dashboard/${segments[1]}/documents`,
});
breadcrumbs.push({
label: sectionLabel,
href: `/dashboard/${segments[1]}/documents`,
});
breadcrumbs.push({ label: documentLabel });
return breadcrumbs;
}
// Handle sources sub-sections
if (section === "sources") {
@ -81,7 +127,7 @@ export function DashboardBreadcrumb() {
add: "Add Sources",
};
const sourceLabel = sourceLabels[subSection] || subSectionLabel;
const sourceLabel = sourceLabels[subSection] || subSection;
breadcrumbs.push({
label: "Sources",
href: `/dashboard/${segments[1]}/sources`,
@ -98,7 +144,7 @@ export function DashboardBreadcrumb() {
webpage: t("add_webpages"),
};
const documentLabel = documentLabels[subSection] || subSectionLabel;
const documentLabel = documentLabels[subSection] || subSection;
breadcrumbs.push({
label: t("documents"),
href: `/dashboard/${segments[1]}/documents`,
@ -160,7 +206,7 @@ export function DashboardBreadcrumb() {
manage: t("manage_connectors"),
};
const connectorLabel = connectorLabels[subSection] || subSectionLabel;
const connectorLabel = connectorLabels[subSection] || subSection;
breadcrumbs.push({
label: t("connectors"),
href: `/dashboard/${segments[1]}/connectors`,
@ -170,6 +216,7 @@ export function DashboardBreadcrumb() {
}
// Handle other sub-sections
let subSectionLabel = subSection.charAt(0).toUpperCase() + subSection.slice(1);
const subSectionLabels: Record<string, string> = {
upload: t("upload_documents"),
youtube: t("add_youtube"),