Skip to content

Knowledge Base: Preview functionality#192

Open
Ayush8923 wants to merge 8 commits into
mainfrom
feat/collection-document-preview
Open

Knowledge Base: Preview functionality#192
Ayush8923 wants to merge 8 commits into
mainfrom
feat/collection-document-preview

Conversation

@Ayush8923
Copy link
Copy Markdown
Collaborator

@Ayush8923 Ayush8923 commented Jun 5, 2026

Issue: #184

Summary:

  • Some of the document extension the preview not properly work like .docs and .txt file, so fix the preview functionality for this and if the not able to preview then some prompt will show so that user know this file not able to preview.
  • Implement the download functionality corresponding to the every file so user can download the file manually too.
  • Refactored scrollbar styling to apply globally across the application.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Refactors document preview flow with shared CSV utilities and preview source logic, adds a same-origin preview proxy route, composes a refactored preview modal and CSV preview component, consolidates types, updates apiClient auth handling, adds a TTS barrel, and moves scrollbar styling to global rules.

Changes

Document Preview System Refactoring

Layer / File(s) Summary
CSV Parsing Utilities
app/lib/utils/csv.ts
New utility module adds parseCsvRow and parseCsv functions to handle CSV parsing with quoted-field and escaped-quote support, replacing in-file implementations.
Document Preview Source Logic
app/lib/utils/documentPreview.ts
Introduces DocumentPreviewKind/DocumentPreviewSource and getDocumentPreviewSource that classifies extensions and routes CSV via same-origin proxy, uses native URLs for images/text, and builds Office/Google viewer embeds.
Document Preview API Route
app/api/document/[document_id]/preview/route.ts
Adds GET handler that proxies signed URL requests server-side, validates presence, streams content with Cache-Control: private, max-age=300, and returns structured JSON errors for missing URLs or upstream failures.
CSV Preview Component
app/components/knowledge-base/CsvPreview.tsx
Client component fetches CSV via signed/proxy URL with API-key auth, parses CSV, guards against post-unmount updates, and renders loading/error/empty or a scrollable table.
Document Preview Modal Refactor
app/components/knowledge-base/DocumentPreviewModal.tsx
Refactors into DocumentSidebar, PreviewHeader, PreviewPane, and PreviewFallback, adds per-kind iframe timeouts, memoized preview source computation, and conditional iframe/CSV/fallback rendering with loader overlay.
apiClient Auth Handling
app/lib/apiClient.ts
Removes automatic retry logic from apiFetch and adds apiFetchResponse that returns raw Response and implements silent refresh-on-401 with /api/auth/* exemption and auth-expired dispatch on refresh failure.
Type Consolidation
app/lib/types/speechToText.ts, app/hooks/useSttData.ts, app/lib/types/document.ts
Moves UseSttDataResult to shared types, and adds document-detail and preview prop/type interfaces used by the preview components.
Module Organization
app/components/text-to-speech/index.ts, app/(main)/text-to-speech/page.tsx, app/components/text-to-speech/DatasetsTab.tsx, app/components/evaluations/DatasetsTab.tsx, app/components/text-to-speech/TTSDatasetCard.tsx
Adds TTS barrel exports, updates page/components to import named exports, consolidates CSV parsing imports in DatasetsTab components, and adjusts relative import path.
Scrollbar Styling and UI Polish
app/globals.css, app/components/analytics/BreakdownPanel.tsx, app/components/knowledge-base/CollectionDetail.tsx
Moves scrollbar styling from class-scoped .custom-scroll-accent to global ::-webkit-scrollbar* and html rules, removes class usage, and changes Preview button variant to primary.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant PreviewRoute
  participant UpstreamHost
  Client->>PreviewRoute: GET /api/document/{id}/preview
  PreviewRoute->>PreviewRoute: fetch document detail via apiClient (include_url=true)
  PreviewRoute->>UpstreamHost: server-fetch signed_url (GET signed_url)
  UpstreamHost-->>PreviewRoute: 200 + Content-Type + body stream
  PreviewRoute-->>Client: 200 streamed body (Content-Type preserved, Cache-Control: private, max-age=300)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • nishika26
  • Prajna1999

Poem

🐰 I hopped through CSVs, fields tucked tight,
I watched iframes wait, then timed out light,
A proxy stream hummed, content flowed through,
Barrels gathered imports, types tidy and true,
The rabbit cheers — previews now view!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Knowledge Base: Preview functionality' directly reflects the main objectives: adding preview functionality for the knowledge base with document preview modals, CSV preview components, and document preview route handlers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/collection-document-preview

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.

@Ayush8923 Ayush8923 self-assigned this Jun 5, 2026
Copy link
Copy Markdown

@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: 5

🧹 Nitpick comments (1)
app/components/text-to-speech/TTSDatasetCard.tsx (1)

5-5: ⚡ Quick win

Use @/ import alias for consistency with coding guidelines.

This file now uses a relative import (./DatasetDescription) while other imports use the @/ alias (lines 3-4). As per coding guidelines, the project should consistently use the @/ import alias for all imports.

♻️ Suggested fix for consistency
-import TTSDatasetDescription from "./DatasetDescription";
+import { DatasetDescription as TTSDatasetDescription } from "`@/app/components/text-to-speech`";

Or if not using the barrel export:

-import TTSDatasetDescription from "./DatasetDescription";
+import TTSDatasetDescription from "`@/app/components/text-to-speech/DatasetDescription`";

As per coding guidelines: Use the import alias @/ to import from the project root as configured in tsconfig.json.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/text-to-speech/TTSDatasetCard.tsx` at line 5, Replace the
relative import of the DatasetDescription module with the project root alias
import to follow the coding guidelines: update the import that brings in
TTSDatasetDescription (currently `./DatasetDescription`) to use the `@/` alias
variant that other files use and ensure the imported symbol name remains
TTSDatasetDescription; no other code changes needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/api/document/`[document_id]/preview/route.ts:
- Line 46: The fetch to signedUrl (const upstream = await fetch(signedUrl)) has
no timeout; wrap the request with an AbortController and a bounded timer (e.g.,
UPSTREAM_FETCH_TIMEOUT_MS) so you pass controller.signal into fetch and call
controller.abort() when the timer elapses, clear the timeout on success or
failure to avoid leaks, and ensure you handle AbortError when awaiting upstream
to return a 504/appropriate error from the route handler.
- Around line 33-44: The route currently ignores the apiClient response status
and treats any non-success as "Document has no signed URL"; update the logic
around apiClient(...) and the DocumentDetailEnvelope handling to first check the
response status and propagate it (returning NextResponse with that status) and
extract the backend error message using the standard extractor (body.error ||
body.message || body.detail or extractErrorMessage(body, fallback)) before you
access signed_url; only if the call succeeded and signedUrl
(detail.data?.signed_url || detail.signed_url) is missing should you return the
404 "Document has no signed URL" error.

In `@app/components/knowledge-base/DocumentPreviewModal.tsx`:
- Around line 52-64: The iframe timeout state persists across modal reopens
because the useEffect that manages setFrameTimedOut/setIsFrameLoading doesn't
depend on the modal open state; update the effect around useEffect to include
the open prop in the dependency array and gate the timeout logic with a check
for open (skip timeout work while closed). On open becoming false immediately
reset setFrameTimedOut(false) and setIsFrameLoading(false); when open is true
run the existing logic (checking usesIframe and previewUrl, starting the timer
using IFRAME_TIMEOUT_MS[kind], and clearing it in the cleanup). Ensure you
reference the same symbols: useEffect, open, previewDoc?.id, previewUrl,
usesIframe, kind, IFRAME_TIMEOUT_MS, setFrameTimedOut, setIsFrameLoading.

In `@app/lib/utils/csv.ts`:
- Around line 31-34: The parseCsv function incorrectly splits input on /\r?\n/
before parsing, breaking quoted cells that contain embedded newlines; update
parseCsv to split into records using a quote-aware algorithm instead of a plain
newline split (e.g., iterate through the input and accumulate characters/lines
until parseCsvRow would see balanced quotes or use a regex that matches CSV
records not inside quotes) and then call parseCsvRow for each complete record;
ensure you still derive headers from the first complete record and produce rows
by mapping parseCsvRow over remaining complete records (refer to parseCsv and
parseCsvRow to locate the logic to change).

In `@app/lib/utils/documentPreview.ts`:
- Around line 81-93: The current preview logic in documentPreview.ts returns
external viewer URLs that include doc.signed_url (seen where OFFICE_EXTS and
GOOGLE_EXTS are handled), leaking time-bound signed URLs to third parties;
change this to route previews through an internal preview proxy endpoint (or
generate a short-lived proxy token) instead of embedding doc.signed_url directly
— modify the OFFICE_EXTS/GOOGLE_EXTS branches to call your server-side preview
proxy (e.g., /internal/preview?docId=... or a proxy token) so the server fetches
the signed document and forwards it to Microsoft/Google viewers or renders it
without exposing doc.signed_url, and ensure doc.signed_url is never interpolated
into external URLs anywhere in documentPreview.ts.

---

Nitpick comments:
In `@app/components/text-to-speech/TTSDatasetCard.tsx`:
- Line 5: Replace the relative import of the DatasetDescription module with the
project root alias import to follow the coding guidelines: update the import
that brings in TTSDatasetDescription (currently `./DatasetDescription`) to use
the `@/` alias variant that other files use and ensure the imported symbol name
remains TTSDatasetDescription; no other code changes needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4363411a-9957-47e8-8d55-06d034e280c3

📥 Commits

Reviewing files that changed from the base of the PR and between 706ad03 and 9402baf.

📒 Files selected for processing (15)
  • app/(main)/text-to-speech/page.tsx
  • app/api/document/[document_id]/preview/route.ts
  • app/components/analytics/BreakdownPanel.tsx
  • app/components/evaluations/DatasetsTab.tsx
  • app/components/knowledge-base/CollectionDetail.tsx
  • app/components/knowledge-base/CsvPreview.tsx
  • app/components/knowledge-base/DocumentPreviewModal.tsx
  • app/components/text-to-speech/DatasetsTab.tsx
  • app/components/text-to-speech/TTSDatasetCard.tsx
  • app/components/text-to-speech/index.ts
  • app/globals.css
  • app/hooks/useSttData.ts
  • app/lib/types/speechToText.ts
  • app/lib/utils/csv.ts
  • app/lib/utils/documentPreview.ts

Comment thread app/api/document/[document_id]/preview/route.ts
Comment thread app/api/document/[document_id]/preview/route.ts
Comment thread app/components/knowledge-base/DocumentPreviewModal.tsx
Comment thread app/lib/utils/csv.ts
Comment thread app/lib/utils/documentPreview.ts
Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
app/lib/types/document.ts (1)

11-18: 💤 Low value

Consider adding JSDoc to clarify the envelope pattern.

The DocumentDetailEnvelope structure allows signed_url and fname at both the top level (via extension) and nested in the optional data field. This appears intentional to support API response variations, but the design may not be immediately obvious to future maintainers.

Adding JSDoc comments would clarify:

  • Why DocumentDetail fields are all optional despite "Detail" suggesting more info
  • The fallback pattern between data?.signed_url and top-level signed_url
  • That these types model API response shapes rather than domain entities
📝 Example JSDoc annotations
+/**
+ * Partial document metadata returned by the document detail API.
+ * Fields are optional as the API may return incomplete data.
+ */
 export interface DocumentDetail {
   signed_url?: string;
   fname?: string;
 }

+/**
+ * Document detail API response envelope.
+ * Supports both top-level fields and nested `data` for flexibility.
+ */
 export interface DocumentDetailEnvelope extends DocumentDetail {
   data?: DocumentDetail;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/lib/types/document.ts` around lines 11 - 18, Add JSDoc comments to
DocumentDetail and DocumentDetailEnvelope to document the envelope pattern:
explain that DocumentDetail's fields (signed_url, fname) are optional because
these types model API response shapes (not domain entities), describe that
DocumentDetailEnvelope extends DocumentDetail and may also carry a nested data?:
DocumentDetail as a fallback, and state the intended precedence (prefer
data?.signed_url/fname if present, otherwise use top-level signed_url/fname) so
future maintainers understand the design and lookup behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/lib/apiClient.ts`:
- Around line 276-286: The current early-return logic in apiFetchResponse
incorrectly returns for all non-401 responses, preventing detection of revoked
sessions; change the flow so you return immediately only when res.ok, but for
non-ok responses check for a revoked-session signal (e.g., if res.status === 403
then read/parsethe response body/text and detect the string "revoked") and call
dispatchAuthExpired() when found; keep the existing guard for auth endpoints
(url.startsWith("/api/auth/")) to avoid auto-refresh, continue to use
tryRefreshToken() and doFetch() for 401 handling, and ensure you still return
the original response after dispatching AUTH_EXPIRED.

---

Nitpick comments:
In `@app/lib/types/document.ts`:
- Around line 11-18: Add JSDoc comments to DocumentDetail and
DocumentDetailEnvelope to document the envelope pattern: explain that
DocumentDetail's fields (signed_url, fname) are optional because these types
model API response shapes (not domain entities), describe that
DocumentDetailEnvelope extends DocumentDetail and may also carry a nested data?:
DocumentDetail as a fallback, and state the intended precedence (prefer
data?.signed_url/fname if present, otherwise use top-level signed_url/fname) so
future maintainers understand the design and lookup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a13efe7d-1fdd-47a9-8bed-4b77f4dcedc6

📥 Commits

Reviewing files that changed from the base of the PR and between 9402baf and 81b8f38.

📒 Files selected for processing (6)
  • app/api/document/[document_id]/preview/route.ts
  • app/components/knowledge-base/CsvPreview.tsx
  • app/components/knowledge-base/DocumentPreviewModal.tsx
  • app/lib/apiClient.ts
  • app/lib/types/document.ts
  • app/lib/utils/documentPreview.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/components/knowledge-base/CsvPreview.tsx
  • app/api/document/[document_id]/preview/route.ts
  • app/components/knowledge-base/DocumentPreviewModal.tsx

Comment thread app/lib/apiClient.ts
Comment thread app/components/knowledge-base/CsvPreview.tsx
@Ayush8923 Ayush8923 linked an issue Jun 5, 2026 that may be closed by this pull request
Ayush8923 and others added 2 commits June 5, 2026 15:12
Co-authored-by: Prashant Vasudevan <71649489+vprashrex@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Knowledge Base: Preview functionality issue

2 participants