Skip to content

Conversation

@naSim087
Copy link
Contributor

@naSim087 naSim087 commented Sep 4, 2025

Description

earlier while adding a new collection , ui listed same collection twice
fix
removed the duplicate listing bug using the map

Testing

Additional Notes

Summary by CodeRabbit

  • New Features

    • Folder contents now show clearer metadata (last updated, updated by); folders default to closed and newly created collections open automatically.
  • Bug Fixes

    • Improved deduplication and merging of backend updates to prevent duplicate collections and preserve folder open/closed state and existing items across fetch, create, update, and uploads.
    • Enhanced error handling and toast messages for folder/file loading and previews.
  • Style

    • Refined copy, wrapping, and layout in the document viewer and modal headers for readability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 4, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Replaces array-based collection state updates with Map-based dedupe/merge keyed by collection ID across fetch, create, add-files, edit, and upload flows; preserves per-collection UI state (isOpen, items), normalizes lastUpdated/updatedBy/files, and improves folder-loading error handling and messages.

Changes

Cohort / File(s) Summary
Collections state & folder/file handling
frontend/src/routes/_authenticated/knowledgeManagement.tsx
Replace array mutations with Map-based merge/dedup by collection ID for fetch/create/add-files/edit/upload; preserve isOpen and items; normalize/derive fields (lastUpdated, updatedBy, files/totalCount); children default isOpen:false; add try/catch + toast on folder fetches; refine error extraction/messages and minor JSX/formatting tweaks.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant UI as KnowledgeManagement UI
  participant S as CollectionsState (Map)
  participant API as Backend

  U->>UI: Load / Refresh
  UI->>API: fetchCollections()
  API-->>UI: collections[]
  UI->>S: mergeFetchedCollections(collections[]) /* dedupe by id, preserve isOpen/items */
  S-->>UI: collections[] (deduped)

  U->>UI: Create / Add files / Edit / Upload
  UI->>API: submitChange(...)
  API-->>UI: updatedCollection
  UI->>S: mergeSingleCollection(updatedCollection)
  S-->>UI: collections[] (updated)
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant UI as KnowledgeManagement UI
  participant API as Backend
  participant S as CollectionsState (Map)

  U->>UI: Expand folder
  UI->>API: fetchFolderContents(folderId)
  alt success
    API-->>UI: children[]
    UI->>S: insertChildren(folderId, children with isOpen=false, lastUpdated, updatedBy)
    S-->>UI: updated tree
  else error
    API--x UI: error
    UI->>UI: console.error + toast("Could not load folder")
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–70 minutes

Possibly related PRs

Suggested reviewers

  • zereraz
  • shivamashtikar
  • kalpadhwaryu
  • junaid-shirur
  • devesh-juspay

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "fix: deduplicate listing collection items" is concise and directly reflects the main change described in the PR (removing duplicate collection listings via a Map-based dedupe/merge), so it accurately communicates the primary fix to reviewers scanning history. It is specific enough to identify the problem area without including noisy file lists or vague terms. The phrasing follows common commit conventions and is appropriate for this changeset.

Poem

I hopped through arrays and cleared the fray,
With Map and whiskers I kept duplicates at bay.
Folders fetch tidy, children set to rest,
lastUpdated and updatedBy now dressed their best.
A snug, orderly burrow — small rabbit, big jest. 🥕

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/collectionListing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @naSim087, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical UI bug where knowledge base collections were appearing as duplicates, particularly after creation or updates. The changes refactor the collection state management to ensure uniqueness and consistency in the displayed list of collections.

Highlights

  • Collection Deduplication Logic: Implemented a Map-based deduplication strategy across several setCollections calls (e.g., on initial fetch, after creating a new collection, after adding files, and after editing a collection). This ensures that collections are uniquely identified by their ID, preventing duplicate entries in the UI.
  • UI Rendering Filter: Added a filter to the collection rendering logic to temporarily hide the collection currently being uploaded, preventing it from appearing twice during the upload process.
  • React Key Optimization: Updated the React list key for collections from 'index' to 'collection.id', which is a best practice for stable list rendering and helps React correctly identify and update list items, especially important with dynamic data and deduplication.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request fixes a bug where collections were listed multiple times in the UI. The fix involves using a Map to deduplicate collections by their ID when updating the state, which is a solid approach. The changes correctly preserve UI state like whether a collection is open. I've identified a potential runtime error and an opportunity to refactor duplicated code for better maintainability. Overall, good work on fixing the duplication bug.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (8)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (8)

483-504: Type fetchedCollections to Collection[] for compile-time safety.

Prevents accidental field drift (like totalCount vs totalItems).

-          const fetchedCollections = data.map((collection: CollectionType) => ({
+          const fetchedCollections: Collection[] = data.map((collection: CollectionType) => ({
             id: collection.id,
             name: collection.name,
             description: collection.description,
             files: collection.totalItems || 0,
             items: [],
             isOpen: false,

505-526: Strongly type the dedup Map and loop.

Avoids any leaks and future type regressions.

-          const collectionsMap = new Map()
+          const collectionsMap = new Map<string, Collection>()
...
-          fetchedCollections.forEach((col: any) => {
+          fetchedCollections.forEach((col: Collection) => {

628-640: Comment and typing nits: it’s Map-based, not Set-based; also type the Map.

Minor clarity/readability improvement.

-      // Use Set-based approach to prevent duplicates
+      // Use Map-based approach to prevent duplicates
       setCollections((prev) => {
-        const collectionsMap = new Map()
+        const collectionsMap = new Map<string, Collection>()

1214-1225: Avoid name-based filtering during uploads; prefer stable IDs.

When adding files to an existing collection, filtering by name can hide a different collection that (rarely) shares the same name. Using an ID is more robust. This requires tracking the uploading collection ID in state (and localStorage) alongside the name.

I can provide a small patch to:

  • extend the persisted upload state with uploadingCollectionId?: string
  • set it in handleAddFilesToCollection
  • prefer ID-based filtering if available, else fallback to name
    Would you like me to draft that?

1230-1260: Minimize direct nested mutations for safer state updates.

This block mutates coll and nested nodes before setCollections. It works because you cloned the top-level array, but nested references remain shared. Consider immutable updates (return new objects) to reduce accidental shared state bugs.

If you want, I can refactor this toggle path to a pure update (map + structural sharing) without deep mutations.


391-393: Trim collection names before comparison to be defensive.

Whitespace differences could bypass the equality check.

-              collection.name.toLowerCase() ===
-              uploadingCollectionName.toLowerCase(),
+              collection.name.trim().toLowerCase() ===
+              uploadingCollectionName.trim().toLowerCase(),

120-122: Nit: copy tweaks are fine.

“Loading document…” string changes are harmless.


197-199: Nit: copy tweaks are fine.

“Select a document to view” formatting looks good.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5684dc4 and a89b44a.

📒 Files selected for processing (1)
  • frontend/src/routes/_authenticated/knowledgeManagement.tsx (14 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)
frontend/src/types/knowledgeBase.ts (2)
  • Collection (1-18)
  • CollectionItem (20-58)
frontend/src/utils/fileUtils.ts (3)
  • FileNode (140-149)
  • uploadFileBatch (195-234)
  • buildFileTree (151-192)
frontend/src/api.ts (1)
  • api (4-4)
🔇 Additional comments (7)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (7)

1309-1430: LGTM: folder lazy-load with Map-merge and consistent shape.

The tree toggle fetch builds children with files, lastUpdated, updatedBy, and preserves isOpen consistently. Looks good.


1552-1553: LGTM: clearer modal title with folder context.

The “Add files to … / …” header improves clarity.


678-686: LGTM: reusing the creation modal for add-files flow.

Passing folder context and pre-filling the name is clean.


722-726: LGTM: propagate parentId to uploads to preserve hierarchy.

Upload API call correctly includes parentId when targeting a folder.


744-777: LGTM: post-upload refresh uses Map-merge and rebuilds tree.

Merges without duplication and preserves UI state.


891-919: LGTM: update-by-ID with Map-merge prevents duplicate entries after rename.

Good dedup and state preservation.


29-32: Type-only imports: good.

Using import type prevents runtime bloat.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (2)

856-887: Use totalItems after delete to keep counts accurate.

-              files: updatedCl.totalCount || 0,
+              files: updatedCl.totalItems || 0,

633-650: Creation flow: use totalItems instead of totalCount.
Ensures correct initial file count and canonical field.

-        files: updatedCl.totalCount || selectedFiles.length,
+        files: updatedCl.totalItems || selectedFiles.length,
...
-        totalCount: updatedCl.totalCount,
+        totalCount: updatedCl.totalItems,
♻️ Duplicate comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

525-550: Type the Map and loop; consider extracting a reusable merge-dedup helper.
Reimplements the same pattern found elsewhere; typing prevents regressions.

Apply:

-          const collectionsMap = new Map()
+          const collectionsMap = new Map<string, Collection>()
...
-          fetchedCollections.forEach((col: any) => {
+          fetchedCollections.forEach((col: Collection) => {

Optional helper (outside this hunk):

function mergeCollections(prev: Collection[], next: Collection[]): Collection[] {
  const m = new Map<string, Collection>()
  prev.forEach((c) => m.set(c.id, c))
  next.forEach((c) => {
    const existing = m.get(c.id)
    m.set(
      c.id,
      existing ? { ...c, isOpen: existing.isOpen, items: existing.items } : c,
    )
  })
  return Array.from(m.values())
}

410-458: Use totalItems, add typing, and sort before set to ensure correct counts and stable order.
Current mapping still reads legacy totalCount and uses untyped Map; the returned array isn’t sorted here.

Apply:

-            const fetchedCollections = data.map(
+            const fetchedCollections: Collection[] = data.map(
               (collection: CollectionType) => ({
                 id: collection.id,
                 name: collection.name,
                 description: collection.description,
-                files: collection.totalCount || 0,
+                files: collection.totalItems || 0,
                 items: [],
                 isOpen: false,
                 lastUpdated: new Date(collection.updatedAt).toLocaleString(
                   "en-GB",
                   {
                     day: "numeric",
                     month: "short",
                     year: "numeric",
                     hour: "2-digit",
                     minute: "2-digit",
                   },
                 ),
                 updatedBy: collection.lastUpdatedByEmail || "Unknown",
-                totalCount: collection.totalCount,
+                totalCount: collection.totalItems,
                 isPrivate: collection.isPrivate,
               }),
             )
 
             // Use Map to deduplicate by ID
             setCollections((prev) => {
-              const collectionsMap = new Map()
+              const collectionsMap = new Map<string, Collection>()
               // First add existing collections (to preserve any state like isOpen)
               prev.forEach((col) => collectionsMap.set(col.id, col))
               // Then add/update with fetched collections
-              fetchedCollections.forEach((col: any) => {
+              fetchedCollections.forEach((col: Collection) => {
                 const existing = collectionsMap.get(col.id)
                 if (existing) {
                   // Preserve certain states while updating data
                   collectionsMap.set(col.id, {
                     ...col,
                     isOpen: existing.isOpen,
                     items: existing.items,
                   })
                 } else {
                   collectionsMap.set(col.id, col)
                 }
               })
-
-              return Array.from(collectionsMap.values())
+              const sorted = sortCollectionsByUpdated(
+                Array.from(collectionsMap.values()),
+              )
+              return sorted
             })

772-809: Guard against spreading undefined and use totalItems.
Spreading collectionsMap.get(...) can throw if missing; also keep to totalItems to avoid zero/incorrect counts.

Apply:

-        const collectionsMap = new Map()
+        const collectionsMap = new Map<string, Collection>()
...
-        const updatedCollection = {
-          ...collectionsMap.get(addingToCollection.id),
-          files: updatedCl.totalCount || 0,
+        const base =
+          collectionsMap.get(addingToCollection.id) ?? {
+            id: addingToCollection.id,
+            name: addingToCollection.name,
+            description: addingToCollection.description ?? null,
+            files: 0,
+            items: [],
+            isOpen: false,
+            lastUpdated: "",
+            updatedBy: "Unknown",
+            totalCount: 0,
+            isPrivate: false,
+          }
+        const updatedCollection: Collection = {
+          ...base,
+          files: updatedCl.totalItems || 0,
           items: buildFileTree(
             items.map((item: CollectionItem) => ({
               name: item.name,
               type: item.type as "file" | "folder",
               totalFileCount: item.totalFileCount,
               updatedAt: item.updatedAt,
               id: item.id,
               updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
             })),
           ),
           lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
             day: "numeric",
             month: "short",
             year: "numeric",
             hour: "2-digit",
             minute: "2-digit",
           }),
           updatedBy: updatedCl.lastUpdatedByEmail || "Unknown",
         }
🧹 Nitpick comments (5)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (5)

477-495: Avoid parsing localized strings for sorting; keep a stable numeric sort key.
Current regex on toLocaleString is brittle across locales/browsers. Prefer storing updatedAt (ISO) or a numeric sortTs alongside lastUpdated and sort by that.

Example (outside this hunk): add sortTs: Date.parse(updatedAt) when mapping; then implement:

-  return collections.sort((a, b) => { /* parse lastUpdated */ })
+  return [...collections].sort((a, b) => (b as any).sortTs - (a as any).sortTs)

I can provide a scoped patch that wires sortTs in all mapping sites if you want.


652-668: Comment says “Set-based” but code uses Map; also type the Map.

-      // Use Set-based approach to prevent duplicates
+      // Use Map-based approach to prevent duplicates
-      setCollections((prev) => {
-        const collectionsMap = new Map()
+      setCollections((prev) => {
+        const collectionsMap = new Map<string, Collection>()

923-954: Type the Map in update flow; optional.

-        setCollections((prev) => {
-          const collectionsMap = new Map()
+        setCollections((prev) => {
+          const collectionsMap = new Map<string, Collection>()

1117-1131: Include files count for children (parity with list tree).
Not strictly required for the doc viewer tree, but keeps data uniform.

-                                  n.children = items.map(
+                                  n.children = items.map(
                                     (item: CollectionItem) => ({
                                       id: item.id,
                                       name: item.name,
                                       type: item.type as "file" | "folder",
+                                      files: item.totalFileCount,
                                       lastUpdated: item.updatedAt,
                                       updatedBy:
                                         item.lastUpdatedByEmail ||
                                         user?.email ||
                                         "Unknown",
                                       isOpen: false,
                                       children:
                                         item.type === "folder" ? [] : undefined,
                                     }),
                                   )

1250-1467: Optional UX: show a placeholder card for the in-progress collection rather than hiding it.
Reduces surprise when users don’t see the just-created collection during upload.

I can sketch a lightweight “uploading…” card keyed by uploadingCollectionName if you want it.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a89b44a and d0e3984.

📒 Files selected for processing (1)
  • frontend/src/routes/_authenticated/knowledgeManagement.tsx (14 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)
frontend/src/types/knowledgeBase.ts (2)
  • Collection (1-18)
  • CollectionItem (20-58)
frontend/src/api.ts (1)
  • api (4-4)
frontend/src/utils/fileUtils.ts (3)
  • FileNode (140-149)
  • uploadFileBatch (195-234)
  • buildFileTree (151-192)
🔇 Additional comments (10)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (10)

29-32: Types import: LGTM.


120-122: UX copy: LGTM.


197-199: Empty-state text: LGTM.


391-393: Case-insensitive match: LGTM.


503-524: Initial fetch mapping: LGTM (uses totalItems correctly).


706-714: Add-files modal opener: LGTM.


750-754: Pass parentId for nested uploads: LGTM.


1250-1261: Filtering out the uploading collection to avoid duplicates: LGTM.
Prevents transient double entries during in-flight uploads.


1391-1462: Folder toggle fetch/build path: LGTM.
Uses children lastUpdated/files fields consistently and handles errors.


1588-1588: Modal title path segment: LGTM.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

612-629: New collection: switch to totalItems.

Align with API contract to avoid silent zeros when totalCount alias is dropped.

       const newCollection: Collection = {
         id: updatedCl.id,
         name: updatedCl.name,
         description: updatedCl.description,
-        files: updatedCl.totalCount || selectedFiles.length,
+        files: updatedCl.totalItems || selectedFiles.length,
         lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
           day: "numeric",
           month: "short",
           year: "numeric",
           hour: "2-digit",
           minute: "2-digit",
         }),
         updatedBy: updatedCl.lastUpdatedByEmail || user?.email || "Unknown",
         items: [],
         isOpen: false,
-        totalCount: updatedCl.totalCount,
+        totalCount: updatedCl.totalItems,
         isPrivate: updatedCl.isPrivate,
       }

258-259: Fix TS6133: remove unused openDropdown state.

This breaks the build. Remove the state and its only usage in handleCloseModal.

-  const [openDropdown, setOpenDropdown] = useState<string | null>(null)
+  // removed unused openDropdown state

Also remove the reset call:

-    setOpenDropdown(null)
+    // removed: openDropdown no longer used

827-858: Standardize totals here too (follow-ups).

Elsewhere you moved to totalItems; mirror that in delete refresh to keep fields consistent.

Would you like me to push a patch for this block as well?

♻️ Duplicate comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

895-922: DRY: extract a shared merge/dedup helper.

This Map-based state merge duplicates logic found in fetch and upload flows. Extract to a reusable mergeCollections(prev, fetched) to reduce drift.


412-461: Use totalItems consistently and type the Map.

Avoid mixing legacy totalCount; prefer totalItems everywhere. Also add Map generics to prevent any and tighten types.

-            const fetchedCollections = data.map(
+            const fetchedCollections = data.map(
               (collection: CollectionType) => ({
                 id: collection.id,
                 name: collection.name,
                 description: collection.description,
-                files: collection.totalCount || 0,
+                files: collection.totalItems || 0,
                 items: [],
                 isOpen: false,
                 lastUpdated: new Date(collection.updatedAt).toLocaleString(
                   "en-GB",
                   {
                     day: "numeric",
                     month: "short",
                     year: "numeric",
                     hour: "2-digit",
                     minute: "2-digit",
                   },
                 ),
                 updatedBy: collection.lastUpdatedByEmail || "Unknown",
-                totalCount: collection.totalCount,
+                totalCount: collection.totalItems,
                 isPrivate: collection.isPrivate,
               }),
             )
 
-            // Use Map to deduplicate by ID
+            // Use Map to deduplicate by ID
             setCollections((prev) => {
-              const collectionsMap = new Map()
+              const collectionsMap = new Map<string, Collection>()
 
               // First add existing collections (to preserve any state like isOpen)
               prev.forEach((col) => collectionsMap.set(col.id, col))
 
               // Then add/update with fetched collections
-              fetchedCollections.forEach((col: any) => {
+              fetchedCollections.forEach((col: Collection) => {
                 const existing = collectionsMap.get(col.id)
                 if (existing) {
                   // Preserve certain states while updating data
                   collectionsMap.set(col.id, {
                     ...col,
                     isOpen: existing.isOpen,
                     items: existing.items,
                   })
                 } else {
                   collectionsMap.set(col.id, col)
                 }
               })
 
               return Array.from(collectionsMap.values())
             })

747-781: Possible TypeError: spreading undefined from Map.get().

collectionsMap.get(addingToCollection.id) can be undefined; spreading it will throw. Also standardize on totalItems here.

-        // Update the specific collection
-        const updatedCollection = {
-          ...collectionsMap.get(addingToCollection.id),
-          files: updatedCl.totalCount || 0,
-          items: buildFileTree(
+        // Update the specific collection
+        const existing = collectionsMap.get(addingToCollection.id) as Collection | undefined
+        const updatedCollection: Collection = {
+          ...(existing ?? ({} as Collection)),
+          id: existing?.id ?? addingToCollection.id,
+          name: existing?.name ?? addingToCollection.name,
+          description: existing?.description ?? null,
+          isOpen: existing?.isOpen ?? false,
+          files: updatedCl.totalItems || 0,
+          items: buildFileTree(
             items.map((item: CollectionItem) => ({
               name: item.name,
               type: item.type as "file" | "folder",
               totalFileCount: item.totalFileCount,
               updatedAt: item.updatedAt,
               id: item.id,
               updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
             })),
           ),
           lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
             day: "numeric",
             month: "short",
             year: "numeric",
             hour: "2-digit",
             minute: "2-digit",
           }),
           updatedBy: updatedCl.lastUpdatedByEmail || "Unknown",
-        }
+          totalCount: updatedCl.totalItems,
+          isPrivate: existing?.isPrivate,
+        }
 
         collectionsMap.set(addingToCollection.id, updatedCollection)
🧹 Nitpick comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

631-643: Comment mismatch and missing generics.

The block uses a Map, not a Set; also add Map generics for type safety.

-      // Use Set-based approach to prevent duplicates
+      // Use Map-based approach to prevent duplicates
       setCollections((prev) => {
-        const collectionsMap = new Map()
+        const collectionsMap = new Map<string, Collection>()
 
         // Add existing collections
         prev.forEach((col) => collectionsMap.set(col.id, col))
 
         // Add/update new collection
         collectionsMap.set(newCollection.id, newCollection)
 
         return Array.from(collectionsMap.values())
       })

1217-1261: Guard item fetch with error handling.

Add try/catch and response.ok checks; prevents crashes on non-2xx and improves UX.

-                          if (coll) {
+                          if (coll) {
                             coll.isOpen = !coll.isOpen
                             if (coll.isOpen) {
-                              const response = await api.cl[":id"].items.$get({
-                                param: { id: collection.id },
-                              })
-                              const data = await response.json()
-                              coll.items = buildFileTree(
-                                data.map((item: CollectionItem) => ({
-                                  name: item.name,
-                                  type: item.type as "file" | "folder",
-                                  totalFileCount: item.totalFileCount,
-                                  updatedAt: item.updatedAt,
-                                  id: item.id,
-                                  updatedBy:
-                                    item.lastUpdatedByEmail ||
-                                    user?.email ||
-                                    "Unknown",
-                                })),
-                              )
+                              try {
+                                const response = await api.cl[":id"].items.$get({
+                                  param: { id: collection.id },
+                                })
+                                if (!response.ok) {
+                                  throw new Error(`Failed to fetch items: ${response.status}`)
+                                }
+                                const data = await response.json()
+                                coll.items = buildFileTree(
+                                  data.map((item: CollectionItem) => ({
+                                    name: item.name,
+                                    type: item.type as "file" | "folder",
+                                    totalFileCount: item.totalFileCount,
+                                    updatedAt: item.updatedAt,
+                                    id: item.id,
+                                    updatedBy:
+                                      item.lastUpdatedByEmail ||
+                                      user?.email ||
+                                      "Unknown",
+                                  })),
+                                )
+                              } catch (err) {
+                                console.error("Failed to load collection items", err)
+                                showToast("Error", "Failed to load collection items", true)
+                              }
                             } else {
                               // coll.items = []; // This would clear the items, maybe not desired
                             }
                             setCollections(updatedCollections)
                           }

1084-1098: Optional: include files count in child nodes.

If the Simple tree shows file counts, pass files: item.totalFileCount as in the list view for consistency.

-                                  n.children = items.map(
+                                  n.children = items.map(
                                     (item: CollectionItem) => ({
                                       id: item.id,
                                       name: item.name,
                                       type: item.type as "file" | "folder",
+                                      files: item.totalFileCount,
                                       lastUpdated: item.updatedAt,
                                       updatedBy:
                                         item.lastUpdatedByEmail ||
                                         user?.email ||
                                         "Unknown",
                                       isOpen: false,
                                       children:
                                         item.type === "folder" ? [] : undefined,
                                     }),
                                   )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0e3984 and 37a42b6.

📒 Files selected for processing (1)
  • frontend/src/routes/_authenticated/knowledgeManagement.tsx (14 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (4)
frontend/src/types/knowledgeBase.ts (2)
  • Collection (1-18)
  • CollectionItem (20-58)
frontend/src/utils/fileUtils.ts (3)
  • FileNode (151-160)
  • uploadFileBatch (206-245)
  • buildFileTree (162-203)
frontend/src/api.ts (1)
  • api (4-4)
frontend/src/components/ui/dropdown-menu.tsx (4)
  • DropdownMenu (188-188)
  • DropdownMenuTrigger (189-189)
  • DropdownMenuContent (190-190)
  • DropdownMenuItem (191-191)
🪛 GitHub Actions: TypeScript Build Check
frontend/src/routes/_authenticated/knowledgeManagement.tsx

[error] 258-258: TypeScript error TS6133: 'openDropdown' is declared but its value is never read. (Command: bunx tsc -b)

🔇 Additional comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

485-506: Fetch mapping looks correct.

Good: uses totalItems, preserves UI state fields, and normalizes metadata.


1217-1227: UI duplicate filter looks good.

Filtering the in-progress uploading collection by name avoids transient duplicates during creation. Nicely contained to the view.


393-401: Case-insensitive name match: LGTM.

Robust check for existingCollection during periodic progress polling.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (6)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (6)

678-678: Inconsistent API field usage detected

Line 678 still uses updatedCl.totalCount instead of the expected updatedCl.totalItems field from the API.

Based on past review comments, all totalCount references should be replaced with totalItems. Apply this fix:

-        files: updatedCl.totalCount || selectedFiles.length,
+        files: updatedCl.totalItems || selectedFiles.length,

689-689: Fix API field reference

Similar to above, this should use totalItems instead of totalCount:

-        totalCount: updatedCl.totalCount,
+        totalCount: updatedCl.totalItems,

816-839: Critical: Handle potential undefined Map.get() result

The existing review comment is still valid - spreading the result of collectionsMap.get(addingToCollection.id) can cause a TypeError if the key doesn't exist, since Map.get() returns undefined for missing keys.

Apply the suggested fix:

-        const updatedCollection = {
-          ...collectionsMap.get(addingToCollection.id),
+        const existingCollection = collectionsMap.get(addingToCollection.id);
+        if (existingCollection) {
+          const updatedCollection = {
+            ...existingCollection,

818-818: Fix API field consistency

Replace totalCount with totalItems:

-          files: updatedCl.totalCount || 0,
+          files: updatedCl.totalItems || 0,

894-894: Another totalCount reference to fix

Continue fixing API field references:

-              files: updatedCl.totalCount || 0,
+              files: updatedCl.totalItems || 0,

1371-1398: Important: Fix field mapping for loaded children

The existing review comment correctly identifies that children nodes use updatedAt instead of lastUpdated, which will cause UI display issues. Apply the suggested fix:

-                                      n.children = items.map(
-                                        (item: CollectionItem) => ({
-                                          id: item.id,
-                                          name: item.name,
-                                          type: item.type as "file" | "folder",
-                                          lastUpdated: item.updatedAt,
-                                          updatedBy:
-                                            item.lastUpdatedByEmail ||
-                                            user?.email ||
-                                            "Unknown",
-                                          isOpen: false,
-                                          children:
-                                            item.type === "folder"
-                                              ? []
-                                              : undefined,
-                                        }),
-                                      )
+                                      n.children = items.map(
+                                        (item: CollectionItem) => ({
+                                          id: item.id,
+                                          name: item.name,
+                                          type: item.type as "file" | "folder",
+                                          files: item.totalFileCount,
+                                          lastUpdated: item.updatedAt,
+                                          updatedBy:
+                                            item.lastUpdatedByEmail ||
+                                            user?.email ||
+                                            "Unknown",
+                                          isOpen: false,
+                                          children:
+                                            item.type === "folder"
+                                              ? []
+                                              : undefined,
+                                        }),
+                                      )
🧹 Nitpick comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

273-276: Minor formatting: Remove extra empty lines

These extra empty lines seem unintentional and can be removed for cleaner formatting.

-  const [isFileTreeCollapsed, setIsFileTreeCollapsed] = useState(true)
-
-  // Chat visibility state based on zoom level
-  const [isChatHidden, setIsChatHidden] = useState(false)
-
+  const [isFileTreeCollapsed, setIsFileTreeCollapsed] = useState(true)
+  // Chat visibility state based on zoom level
+  const [isChatHidden, setIsChatHidden] = useState(false)

1044-1045: Minor: Trailing comma inconsistency

The false, parameter has a trailing comma that could be removed for consistency:

-        false,
+        false

1723-1723: Minor: Trailing whitespace

There appears to be trailing whitespace or an empty line that could be cleaned up.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37a42b6 and f4113c9.

📒 Files selected for processing (1)
  • frontend/src/routes/_authenticated/knowledgeManagement.tsx (26 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)
frontend/src/types/knowledgeBase.ts (1)
  • CollectionItem (20-58)
frontend/src/utils/fileUtils.ts (1)
  • buildFileTree (162-219)
frontend/src/api.ts (1)
  • api (4-4)
🔇 Additional comments (19)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (19)

291-291: Good SSR guard implementation

The guard for server-side rendering is properly implemented to prevent window-related errors.


317-330: Event listener management looks solid

The event listener setup and cleanup for zoom detection is well implemented with proper cleanup in the effect's return function.

Also applies to: 333-333


407-407: Good API consistency in parameter naming

Using includeItems: "true" consistently across all API calls maintains good parameter naming consistency.

Also applies to: 467-467, 551-551


494-526: LGTM: Clean implementation of deduplication logic

The implementation correctly uses a Map-based approach to prevent duplicates and preserve UI state. The collection mapping logic is well-structured.


556-590: Good deduplication implementation for initial data fetch

The Map-based approach correctly handles deduplication during the initial collections fetch, maintaining consistency with the PR objectives.


693-704: Excellent Map-based deduplication pattern

This is a clean implementation of Set/Map-based deduplication that prevents duplicate listings while preserving existing UI state. The pattern correctly addresses the PR objective.


809-842: Well-implemented Map-based state update with UI preservation

The Map-based approach correctly preserves existing UI state (isOpen, items) while updating the collection data. This properly addresses the deduplication issue mentioned in the PR objectives.


956-983: Good Map-based collection update pattern

The Map-based approach for updating collection names is well-implemented and consistent with the overall deduplication strategy.


1011-1014: Simple and effective collection removal

The collection removal logic is straightforward and correct - using filter to remove the deleted collection from state.


1100-1114: Improved error handling implementation

The enhanced error handling with better error message extraction and consistent toast messaging is a good improvement.


1216-1227: Clean button layout with proper line formatting

The multi-line button properties are well-formatted and the conditional title text is properly implemented.


1267-1278: Improved SVG icon formatting

The SVG icon is now properly formatted across multiple lines for better readability while maintaining functionality.


1288-1292: Good backdrop styling

The backdrop styling and click handler for the chat overlay are properly implemented.


1457-1466: Good button formatting and disabled state handling

The button formatting across multiple lines is clean and the disabled state properly prevents actions during uploads.


1472-1494: Well-structured upload progress display

The upload progress display with file counts and batch information provides good user feedback during the upload process.


1534-1543: Clean chevron icon formatting

The chevron icons are properly formatted with consistent styling and good visual hierarchy.


1559-1567: Good conditional interaction handling

The conditional logic properly disables interactions during uploads while maintaining the existing dropdown functionality.


1580-1582: Consistent disabled state pattern

The disabled state handling in dropdown menu items follows the same pattern used elsewhere in the component.


1891-1904: Good props organization for CollectionFileUpload

The props are well-organized and clearly show all the necessary data and callbacks being passed to the upload component.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)

686-686: Use totalItems instead of totalCount (prevents wrong files count).

These paths still use totalCount; backend and earlier mappings use totalItems. This causes incorrect file counts and inconsistent UI.

-        files: updatedCl.totalCount || selectedFiles.length,
+        files: updatedCl.totalItems || selectedFiles.length,
@@
-        totalCount: updatedCl.totalCount,
+        totalCount: updatedCl.totalItems,
@@
-          files: updatedCl.totalCount || 0,
+          files: updatedCl.totalItems || 0,
@@
-              files: updatedCl.totalCount || 0,
+              files: updatedCl.totalItems || 0,

Search for any remaining totalCount usages in this file:

#!/bin/bash
rg -n -C2 '\btotalCount\b' --glob 'frontend/src/routes/_authenticated/knowledgeManagement.tsx'

Also applies to: 707-707, 836-836, 912-912


494-529: Extract a single “API → UI collection” mapper to remove duplication.

The data shaping logic is repeated across fetch, upload-complete refresh, create, add-files, and delete-item flows. Centralize mapping to reduce drift and keep totalItems/files/lastUpdated consistent.

If helpful, I can push a helper like mapApiCollectionToUi(collection, {items?, openOverride?}). Want me to draft it?

Also applies to: 558-592, 676-709, 827-860, 907-935


827-860: Fix potential TypeError when spreading an undefined collection.

Spreading collectionsMap.get(addingToCollection.id) will throw if the key is missing.

-      setCollections((prev) => {
-        const collectionsMap = new Map()
-        // Add existing collections
-        prev.forEach((col) => collectionsMap.set(col.id, col))
-        // Update the specific collection
-        const updatedCollection = {
-          ...collectionsMap.get(addingToCollection.id),
-          files: updatedCl.totalCount || 0,
-          items: buildFileTree(
-            items.map((item: CollectionItem) => ({
-              name: item.name,
-              type: item.type as "file" | "folder",
-              totalFileCount: item.totalFileCount,
-              updatedAt: item.updatedAt,
-              id: item.id,
-              updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
-            })),
-          ),
-          lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
-            day: "numeric",
-            month: "short",
-            year: "numeric",
-            hour: "2-digit",
-            minute: "2-digit",
-          }),
-          updatedBy: updatedCl.lastUpdatedByEmail || "Unknown",
-        }
-        collectionsMap.set(addingToCollection.id, updatedCollection)
-        return Array.from(collectionsMap.values())
-      })
+      setCollections((prev) => {
+        const collectionsMap = new Map(prev.map((c) => [c.id, c]))
+        const existing = collectionsMap.get(addingToCollection.id)
+        if (!existing) {
+          // Key missing; construct safely from backend response
+          collectionsMap.set(addingToCollection.id, {
+            id: updatedCl.id,
+            name: updatedCl.name,
+            description: updatedCl.description,
+            files: updatedCl.totalItems || 0,
+            items: buildFileTree(
+              items.map((item: CollectionItem) => ({
+                name: item.name,
+                type: item.type as "file" | "folder",
+                totalFileCount: item.totalFileCount,
+                updatedAt: item.updatedAt,
+                id: item.id,
+                updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
+              })),
+            ),
+            lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
+              day: "numeric",
+              month: "short",
+              year: "numeric",
+              hour: "2-digit",
+              minute: "2-digit",
+            }),
+            updatedBy: updatedCl.lastUpdatedByEmail || "Unknown",
+            isPrivate: updatedCl.isPrivate,
+            totalCount: updatedCl.totalItems,
+            isOpen: true,
+          })
+        } else {
+          const updatedCollection = {
+            ...existing,
+            files: updatedCl.totalItems || 0,
+            items: buildFileTree(
+              items.map((item: CollectionItem) => ({
+                name: item.name,
+                type: item.type as "file" | "folder",
+                totalFileCount: item.totalFileCount,
+                updatedAt: item.updatedAt,
+                id: item.id,
+                updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
+              })),
+            ),
+            lastUpdated: new Date(updatedCl.updatedAt).toLocaleString("en-GB", {
+              day: "numeric",
+              month: "short",
+              year: "numeric",
+              hour: "2-digit",
+              minute: "2-digit",
+            }),
+            updatedBy: updatedCl.lastUpdatedByEmail || "Unknown",
+          }
+          collectionsMap.set(addingToCollection.id, updatedCollection)
+        }
+        return Array.from(collectionsMap.values())
+      })
🧹 Nitpick comments (6)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (6)

494-531: Preserve per-collection UI state when refreshing after upload.

setCollections(updatedCollections) overwrites isOpen/items for all collections. Merge with previous state to avoid collapsing user-opened trees.

-            setCollections(updatedCollections)
+            setCollections((prev) => {
+              const prevMap = new Map(prev.map((c) => [c.id, c]))
+              return data.map(
+                (collection: CollectionType & { items?: CollectionItem[] }) => {
+                  const existing = prevMap.get(collection.id)
+                  const isNewlyUploaded =
+                    collection.name.toLowerCase() ===
+                    uploadingCollectionName.toLowerCase()
+                  return {
+                    id: collection.id,
+                    name: collection.name,
+                    description: collection.description,
+                    files: collection.totalItems || 0,
+                    items:
+                      existing?.items && existing.items.length > 0
+                        ? existing.items
+                        : buildFileTree(
+                            (collection.items || []).map((item: CollectionItem) => ({
+                              name: item.name,
+                              type: item.type as "file" | "folder",
+                              totalFileCount: item.totalFileCount,
+                              updatedAt: item.updatedAt,
+                              id: item.id,
+                              updatedBy: item.lastUpdatedByEmail || user?.email || "Unknown",
+                            })),
+                          ),
+                    isOpen:
+                      isNewlyUploaded ||
+                      (existing?.isOpen ?? (collection.items || []).length > 0),
+                    lastUpdated: new Date(collection.updatedAt).toLocaleString("en-GB", {
+                      day: "numeric",
+                      month: "short",
+                      year: "numeric",
+                      hour: "2-digit",
+                      minute: "2-digit",
+                    }),
+                    updatedBy: collection.lastUpdatedByEmail || "Unknown",
+                    totalCount: collection.totalItems,
+                    isPrivate: collection.isPrivate,
+                  }
+                },
+              )
+            })

1401-1416: Include files count for children in SimpleFileTree overlay.

Overlay folder expansion omits files: item.totalFileCount; the list view includes it. Add for consistency.

-                                      n.children = items.map(
-                                        (item: CollectionItem) => ({
+                                      n.children = items.map(
+                                        (item: CollectionItem) => ({
                                           id: item.id,
                                           name: item.name,
                                           type: item.type as "file" | "folder",
+                                          files: item.totalFileCount,
                                           lastUpdated: item.updatedAt,
                                           updatedBy:
                                             item.lastUpdatedByEmail ||
                                             user?.email ||
                                             "Unknown",
                                           isOpen: false,
                                           children:
                                             item.type === "folder"
                                               ? []
                                               : undefined,
                                         }),
                                       )

1306-1313: Remove duplicate Tailwind class (double max-w).

Duplicate max-w classes can cause unpredictable styling.

-                <div className="relative bg-white dark:bg-[#1E1E1E] w-[50%] max-w-[50%] max-w-[90vw] h-full shadow-2xl transform transition-transform duration-300 ease-in-out">
+                <div className="relative bg-white dark:bg-[#1E1E1E] w-[50%] max-w-[90vw] h-full shadow-2xl transform transition-transform duration-300 ease-in-out">

744-759: Revoke object URLs to avoid memory leaks from previews.

You create URL.createObjectURL for each selected file but never revoke it on removal/clear.

   const handleRemoveFile = (id: string) => {
-    setSelectedFiles((prev) => prev.filter((f) => f.id !== id))
+    setSelectedFiles((prev) => {
+      const target = prev.find((f) => f.id === id)
+      if (target?.preview) URL.revokeObjectURL(target.preview)
+      return prev.filter((f) => f.id !== id)
+    })
   }
 
   const handleRemoveAllFiles = () => {
-    setSelectedFiles([])
+    setSelectedFiles((prev) => {
+      prev.forEach((f) => f.preview && URL.revokeObjectURL(f.preview))
+      return []
+    })
   }

609-616: Also revoke previews when closing modal.

Ensure previews are cleaned up when closing.

   const handleCloseModal = () => {
+    setSelectedFiles((prev) => {
+      prev.forEach((f) => f.preview && URL.revokeObjectURL(f.preview))
+      return []
+    })
     setShowNewCollection(false)
     setAddingToCollection(null)
     setTargetFolder(null)
     setCollectionName("")
-    setSelectedFiles([])
     setOpenDropdown(null)
   }

711-723: Update comment: this is Map-based, not Set-based.

The comment says “Set-based approach” but the code uses Map. Align to avoid confusion.

-      // Use Set-based approach to prevent duplicates
+      // Use Map-based approach to prevent duplicates
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4113c9 and 927fc9e.

📒 Files selected for processing (1)
  • frontend/src/routes/_authenticated/knowledgeManagement.tsx (27 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (3)
frontend/src/types/knowledgeBase.ts (1)
  • CollectionItem (20-58)
frontend/src/utils/fileUtils.ts (1)
  • buildFileTree (162-219)
frontend/src/api.ts (1)
  • api (4-4)
🔇 Additional comments (1)
frontend/src/routes/_authenticated/knowledgeManagement.tsx (1)

1118-1132: Nice defensive error handling on failed content fetch.

Clear, user-friendly messaging and proper JSON/text fallbacks.

@zereraz zereraz merged commit fcba776 into main Sep 12, 2025
4 checks passed
@zereraz zereraz deleted the fix/collectionListing branch September 12, 2025 10:17
debojyoti-git pushed a commit that referenced this pull request Sep 12, 2025
* fix:duplicate collection listing

* fix:listing of duplicate collection while updating a collection

* fix ai raised issue

* fix:raised issue

* after new collection made level 1 will be shown

---------

Co-authored-by: Rahul Kumar <rahul2004kumar14@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants