feat: Add document count indicators to workspace document management modal (#5207)

* add document counts to non-embedded and embedded documents

* Update logic to not count search filtered documents

* refactor how count is done and rendered

* translations

---------

Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
Marcello Fitton 2026-03-17 13:46:54 -07:00 committed by GitHub
parent 7908c10379
commit 863ce38137
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 76 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import { middleTruncate } from "@/utils/directories";
export default function FolderRow({
item,
totalItems = 0,
selected,
onRowClick,
toggleSelection,
@ -60,6 +61,11 @@ export default function FolderRow({
<p className="whitespace-nowrap overflow-show max-w-[400px]">
{middleTruncate(item.name, 35)}
</p>
{totalItems > 0 && (
<span className="text-theme-text-secondary text-[10px] font-medium ml-1.5 shrink-0">
({totalItems})
</span>
)}
</div>
<p className="col-span-2 pl-3.5" />
<p className="col-span-2 pl-2" />

View File

@ -193,6 +193,11 @@ function Directory({
setContextMenu({ visible: false, x: 0, y: 0 });
};
const totalDocCount = (files?.items ?? []).reduce((acc, folder) => {
if (folder.type === "folder") return folder.items.length + acc;
return acc;
}, 0);
return (
<>
<div className="px-8 pb-8" onContextMenu={handleContextMenu}>
@ -232,6 +237,13 @@ function Directory({
<div className="relative w-[560px] h-[310px] bg-theme-settings-input-bg rounded-2xl overflow-hidden border border-theme-modal-border">
<div className="absolute top-0 left-0 right-0 z-10 rounded-t-2xl text-theme-text-primary text-xs grid grid-cols-12 py-2 px-8 border-b border-white/20 light:border-theme-modal-border bg-theme-settings-input-bg">
<p className="col-span-6">Name</p>
{totalDocCount > 0 && (
<p className="col-span-6 text-right text-theme-text-secondary">
{t(`connectors.directory.total-documents`, {
count: totalDocCount,
})}
</p>
)}
</div>
<div className="overflow-y-auto h-full pt-8">
@ -249,6 +261,7 @@ function Directory({
<FolderRow
key={index}
item={item}
totalItems={item.items?.length ?? 0}
selected={isSelected(
item.id,
item.type === "folder" ? item : null
@ -310,7 +323,6 @@ function Directory({
</div>
)}
</div>
<UploadFile
workspace={workspace}
fetchKeys={fetchKeys}

View File

@ -28,6 +28,10 @@ function WorkspaceDirectory({
}) {
const { t } = useTranslation();
const [selectedItems, setSelectedItems] = useState({});
const embeddedDocCount = (files?.items ?? []).reduce(
(sum, folder) => sum + (folder.items?.length ?? 0),
0
);
const toggleSelection = (item) => {
setSelectedItems((prevSelectedItems) => {
@ -101,7 +105,6 @@ function WorkspaceDirectory({
<div className="shrink-0 w-3 h-3" />
<p className="ml-[7px] text-theme-text-primary">Name</p>
</div>
<p className="col-span-2" />
</div>
<div className="w-full h-[calc(100%-40px)] flex items-center justify-center flex-col gap-y-5">
<PreLoader />
@ -157,7 +160,13 @@ function WorkspaceDirectory({
)}
<p className="ml-[7px] text-theme-text-primary">Name</p>
</div>
<p className="col-span-2" />
{embeddedDocCount > 0 && (
<p className="col-span-2 text-right text-theme-text-secondary pr-2">
{t(`connectors.directory.total-documents`, {
count: embeddedDocCount,
})}
</p>
)}
</div>
<div className="overflow-y-auto h-[calc(100%-40px)]">
{files.items.some((folder) => folder.items.length > 0) ||

View File

@ -590,6 +590,8 @@ const TRANSLATIONS = {
remove_selected: "حذف المحدد",
costs: "*تكلفة ثابتة لإنشاء التمثيلات",
save_embed: "حفظ و تضمين",
"total-documents_one": "{{count}}",
"total-documents_other": "{{count}} المستندات",
},
upload: {
"processor-offline": "غير متاح",

View File

@ -728,6 +728,8 @@ const TRANSLATIONS = {
remove_selected: "Odebrat vybrané",
costs: "*Jednorázové náklady pro embeddingy",
save_embed: "Uložit a vložit",
"total-documents_one": "{{count}} dokument",
"total-documents_other": "{{count}} dokumenty",
},
upload: {
"processor-offline": "Procesor dokumentů nedostupný",

View File

@ -597,6 +597,8 @@ const TRANSLATIONS = {
remove_selected: "Fjern valgte",
costs: "*Engangsomkostning for indlejringer",
save_embed: "Gem og indlejr",
"total-documents_one": "{{count}} dokument",
"total-documents_other": "{{count}} dokumenter",
},
upload: {
"processor-offline": "Dokumentbehandler utilgængelig",

View File

@ -705,6 +705,8 @@ const TRANSLATIONS = {
remove_selected: "Ausgewähltes entfernen",
costs: "*Einmalige Kosten für das Einbetten",
save_embed: "Speichern und Einbetten",
"total-documents_one": "{{count}} Dokument",
"total-documents_other": "{{count}} Dokumente",
},
upload: {
"processor-offline": "Dokumentenprozessor nicht verfügbar",

View File

@ -715,6 +715,8 @@ const TRANSLATIONS = {
directory: {
"my-documents": "My Documents",
"new-folder": "New Folder",
"total-documents_one": "{{count}} document",
"total-documents_other": "{{count}} documents",
"search-document": "Search for document",
"no-documents": "No Documents",
"move-workspace": "Move to Workspace",

View File

@ -715,6 +715,8 @@ const TRANSLATIONS = {
remove_selected: "Eliminar seleccionados",
costs: "*Costo único por incrustaciones",
save_embed: "Guardar e incrustar",
"total-documents_one": "{{count}} documento",
"total-documents_other": "{{count}} documentos",
},
upload: {
"processor-offline": "Procesador de documentos no disponible",

View File

@ -675,6 +675,8 @@ const TRANSLATIONS = {
remove_selected: "Eemalda valitud",
costs: "*Ühekordne embeddingu kulu",
save_embed: "Salvesta ja põimi",
"total-documents_one": "{{count}} dokument",
"total-documents_other": "{{count}} dokumendid",
},
upload: {
"processor-offline": "Dokumenditöötleja pole saadaval",

View File

@ -594,6 +594,8 @@ const TRANSLATIONS = {
remove_selected: "حذف انتخاب‌شده",
costs: "*هزینه یکباره برای ایجاد مدل‌های برداری",
save_embed: "ذخیره و وارد کردن",
"total-documents_one": "{{count}} سند",
"total-documents_other": "{{count}} اسناد",
},
upload: {
"processor-offline":

View File

@ -596,6 +596,8 @@ const TRANSLATIONS = {
remove_selected: "Supprimer la sélection",
costs: "Coûts",
save_embed: "Sauvegarder et intégrer",
"total-documents_one": "{{count}}",
"total-documents_other": "{{count}} documents",
},
upload: {
"processor-offline": "Processeur de documents hors ligne",

View File

@ -679,6 +679,8 @@ const TRANSLATIONS = {
remove_selected: "הסר נבחרים",
costs: "*עלות חד פעמית להטמעות",
save_embed: "שמור והטמע",
"total-documents_one": "{{count}} מסמך",
"total-documents_other": "מסמכים {{count}}",
},
upload: {
"processor-offline": "מעבד המסמכים אינו זמין",

View File

@ -600,6 +600,8 @@ const TRANSLATIONS = {
remove_selected: "Elimina gli elementi selezionati",
costs: "*Costo una tantum per le embedding",
save_embed: "Salva e incorpora",
"total-documents_one": "{{count}} documento",
"total-documents_other": "{{count}} documenti",
},
upload: {
"processor-offline": "Il processore di documenti non è disponibile.",

View File

@ -586,6 +586,8 @@ const TRANSLATIONS = {
remove_selected: "選択したものを削除",
costs: "※埋め込みには一度だけ費用がかかります",
save_embed: "保存して埋め込む",
"total-documents_one": "{{count}} のドキュメント",
"total-documents_other": "{{count}} に関する書類",
},
upload: {
"processor-offline": "ドキュメント処理機能が利用できません",

View File

@ -687,6 +687,8 @@ const TRANSLATIONS = {
remove_selected: "선택 항목 삭제",
costs: "*임베딩 1회 비용",
save_embed: "저장 및 임베딩",
"total-documents_one": "{{count}} 문서",
"total-documents_other": "{{count}} 관련 문서",
},
upload: {
"processor-offline": "문서 처리기가 오프라인 상태입니다",

View File

@ -700,6 +700,8 @@ const TRANSLATIONS = {
remove_selected: "Noņemt atlasītos",
costs: "*Vienreizējas izmaksas iegulšanai",
save_embed: "Saglabāt un iegult",
"total-documents_one": "{{count}} dokumenta",
"total-documents_other": "{{count}} dokumenti",
},
upload: {
"processor-offline": "Dokumentu apstrādātājs nav pieejams",

View File

@ -596,6 +596,8 @@ const TRANSLATIONS = {
remove_selected: "Verwijderen Geselecteerd",
costs: "*Eenmalige kosten voor embedden",
save_embed: "Opslaan en embedden",
"total-documents_one": "{{count}} document",
"total-documents_other": "{{count}} documenten",
},
upload: {
"processor-offline": "Documentverwerker niet beschikbaar",

View File

@ -702,6 +702,8 @@ const TRANSLATIONS = {
remove_selected: "Usuń wybrane",
costs: "*Jednorazowy koszt dodania danych",
save_embed: "Zapisz",
"total-documents_one": "{{count}} dokument",
"total-documents_other": "{{count}} dokumenty",
},
upload: {
"processor-offline": "Procesor dokumentów niedostępny",

View File

@ -685,6 +685,8 @@ const TRANSLATIONS = {
remove_selected: "Remover Selecionados",
costs: "*Custo único para vínculos",
save_embed: "Salvar e Inserir",
"total-documents_one": "{{count}} documento",
"total-documents_other": "{{count}} documentos",
},
upload: {
"processor-offline": "Processador de documentos Indisponível",

View File

@ -448,6 +448,8 @@ const TRANSLATIONS = {
remove_selected: "Elimină selectate",
costs: "*Cost unic pentru embeddings",
save_embed: "Salvează și încorporează",
"total-documents_one": "{{count}}",
"total-documents_other": "{{count}} documente",
},
upload: {
"processor-offline": "Procesorul de documente este offline",

View File

@ -594,6 +594,8 @@ const TRANSLATIONS = {
remove_selected: "Удалить выбранные",
costs: "*Единоразовая стоимость за внедрение",
save_embed: "Сохранить и внедрить",
"total-documents_one": "{{count}} документ",
"total-documents_other": "{{count}} документы",
},
upload: {
"processor-offline": "Процессор документов недоступен",

View File

@ -594,6 +594,8 @@ const TRANSLATIONS = {
remove_selected: "Seçilenleri Kaldır",
costs: "*Gömmeler için tek seferlik maliyet",
save_embed: "Kaydet ve Göm",
"total-documents_one": "{{count}} belgesi",
"total-documents_other": "{{count}} belgeleri",
},
upload: {
"processor-offline": "Belge İşleyici Kullanılamıyor",

View File

@ -591,6 +591,8 @@ const TRANSLATIONS = {
remove_selected: "Xóa Đã chọn",
costs: "*Chi phí một lần cho việc nhúng",
save_embed: "Lưu và Nhúng",
"total-documents_one": "{{count}}",
"total-documents_other": "{{count}}",
},
upload: {
"processor-offline": "Trình xử lý Tài liệu Không khả dụng",

View File

@ -643,6 +643,8 @@ const TRANSLATIONS = {
remove_selected: "移除所选",
costs: "*嵌入时一次性费用",
save_embed: "保存并嵌入",
"total-documents_one": "{{count}} 文件",
"total-documents_other": "{{count}} 类型的文件",
},
upload: {
"processor-offline": "文档处理器不可用",

View File

@ -553,6 +553,8 @@ const TRANSLATIONS = {
remove_selected: "移除選擇的項目",
costs: "*嵌入僅會計費一次",
save_embed: "儲存並嵌入",
"total-documents_one": "{{count}} 文件",
"total-documents_other": "{{count}} 文件",
},
upload: {
"processor-offline": "文件處理器無法使用",