Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion components/datarooms/dataroom-document-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ export default function DataroomDocumentCard({
hasPages:
dataroomDocument.document.versions?.[0]?.hasPages || false,
type: dataroomDocument.document.type,
numPages: null, // Not available in this context
numPages: null,
}}
advancedExcelEnabled={
dataroomDocument.document.advancedExcelEnabled
}
variant="outline"
size="icon"
className="z-10 h-8 w-8 border-gray-200 bg-transparent hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
Expand Down
6 changes: 5 additions & 1 deletion components/documents/document-preview-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface DocumentPreviewButtonProps {
type?: string | null;
numPages?: number | null;
};
advancedExcelEnabled?: boolean;
isProcessing?: boolean;
variant?: "ghost" | "outline" | "default";
size?: "sm" | "default" | "lg" | "icon";
Expand All @@ -25,6 +26,7 @@ interface DocumentPreviewButtonProps {
export function DocumentPreviewButton({
documentId,
primaryVersion,
advancedExcelEnabled = false,
isProcessing = false,
variant = "ghost",
size = "icon",
Expand All @@ -44,7 +46,9 @@ export function DocumentPreviewButton({
// Support image documents
if (primaryVersion.type === "image") return true;

// Don't support sheets, notion, videos, etc.
// Support Excel sheets with advanced mode enabled
if (primaryVersion.type === "sheet" && advancedExcelEnabled) return true;

return false;
};

Expand Down
1 change: 1 addition & 0 deletions components/documents/preview-viewers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { PreviewExcelViewer } from "./preview-excel-viewer";
export { PreviewImageViewer } from "./preview-image-viewer";
export { PreviewPagesViewer } from "./preview-pages-viewer";
export { PreviewViewer } from "./preview-viewer";
58 changes: 58 additions & 0 deletions components/documents/preview-viewers/preview-excel-viewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useState } from "react";

import { DocumentPreviewData } from "@/lib/types/document-preview";
import { cn } from "@/lib/utils";

interface PreviewExcelViewerProps {
documentData: DocumentPreviewData;
onClose: () => void;
}

export function PreviewExcelViewer({
documentData,
onClose,
}: PreviewExcelViewerProps) {
const [iframeLoaded, setIframeLoaded] = useState(false);

const { file, documentName } = documentData;

if (!file) {
return (
<div className="flex h-full w-full items-center justify-center">
<p className="text-gray-400">Excel preview not available</p>
</div>
);
}

const embedUrl = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(file)}&wdPrint=0&action=embedview&wdAllowInteractivity=False`;

return (
<div className="relative h-full w-full overflow-hidden">
{/* Document Title */}
<div className="absolute left-1/2 top-4 z-50 -translate-x-1/2">
<div className="rounded-lg bg-black/20 px-3 py-2 text-white">
<span className="text-sm font-medium">{documentName}</span>
</div>
</div>

{/* Loading indicator */}
{!iframeLoaded && (
<div className="absolute inset-0 flex items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-2 border-white border-t-transparent" />
</div>
)}

{/* Office Online iframe */}
<div className="h-full w-full pt-14 pb-2 px-2">
<iframe
className={cn(
"h-full w-full rounded-md transition-opacity duration-200",
iframeLoaded ? "opacity-100" : "opacity-0",
)}
src={embedUrl}
onLoad={() => setIframeLoaded(true)}
/>
</div>
</div>
);
}
18 changes: 15 additions & 3 deletions components/documents/preview-viewers/preview-viewer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DocumentPreviewData } from "@/lib/types/document-preview";

import { PreviewExcelViewer } from "./preview-excel-viewer";
import { PreviewImageViewer } from "./preview-image-viewer";
import { PreviewPagesViewer } from "./preview-pages-viewer";

Expand All @@ -24,13 +25,24 @@ export function PreviewViewer({ documentData, onClose }: PreviewViewerProps) {
);
}

// Excel/CSV files
if (documentData.fileType === "sheet" && documentData.sheetData) {
// Excel/CSV files with advanced mode
if (
documentData.fileType === "sheet" &&
documentData.advancedExcelEnabled &&
documentData.file
) {
return (
<PreviewExcelViewer documentData={documentData} onClose={onClose} />
);
}

// Excel/CSV files without advanced mode
if (documentData.fileType === "sheet") {
return (
<div className="flex h-full w-full items-center justify-center">
<div className="text-center">
<p className="text-gray-400">
Sheet preview coming soon. Please preview via a shared link.
Enable advanced Excel mode to preview this document.
</p>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions lib/swr/use-dataroom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ export type DataroomFolderDocument = DataroomDocument & {
id: string;
name: string;
type: string;
advancedExcelEnabled?: boolean;
versions?: { id: string; hasPages: boolean }[];
isExternalUpload?: boolean;
_count: {
Expand Down
1 change: 1 addition & 0 deletions lib/types/document-preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface DocumentPreviewData {
fileType: string;
isVertical: boolean;
numPages: number;
advancedExcelEnabled?: boolean;
pages?: {
file: string;
pageNumber: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export default async function handle(
id: true,
name: true,
type: true,
advancedExcelEnabled: true,
versions: {
select: { id: true, hasPages: true },
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export default async function handle(
id: true,
name: true,
type: true,
advancedExcelEnabled: true,
versions: {
select: { id: true, hasPages: true },
},
Expand Down
20 changes: 15 additions & 5 deletions pages/api/teams/[teamId]/documents/[id]/preview-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { NextApiRequest, NextApiResponse } from "next";

import { getServerSession } from "next-auth/next";

import { getTeamStorageConfigById } from "@/ee/features/storage/config";

import { getFile } from "@/lib/files/get-file";
import prisma from "@/lib/prisma";
import { CustomUser } from "@/lib/types";
Expand Down Expand Up @@ -99,6 +101,7 @@ export default async function handle(
fileType: primaryVersion.type,
isVertical: primaryVersion.isVertical,
numPages: primaryVersion.numPages,
advancedExcelEnabled: document.advancedExcelEnabled,
pages: undefined as any,
file: undefined as string | undefined,
sheetData: undefined as any,
Expand All @@ -124,11 +127,18 @@ export default async function handle(
});
returnData.numPages = 1;
} else if (primaryVersion.type === "sheet") {
// Excel/CSV files - preview not supported
return res.status(400).json({
message:
"Sheet preview not available. Please preview via a shared link.",
});
if (document.advancedExcelEnabled) {
// Advanced Excel mode: use Office Online viewer URL
if (!primaryVersion.file.includes("https://")) {
const storageConfig = await getTeamStorageConfigById(document.teamId);
returnData.file = `https://${storageConfig.advancedDistributionHost}/${primaryVersion.file}`;
} else {
Comment on lines +133 to +135
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard advancedDistributionHost before building the preview URL.

getTeamStorageConfigById() returns a config where advancedDistributionHost is optional, so this can emit https://undefined/... and silently break advanced Excel previews for teams without that distribution configured.

Suggested fix
         if (!primaryVersion.file.includes("https://")) {
           const storageConfig = await getTeamStorageConfigById(document.teamId);
+          if (!storageConfig.advancedDistributionHost) {
+            return res.status(503).json({
+              message:
+                "Advanced Excel preview is not configured for this team.",
+            });
+          }
           returnData.file = `https://${storageConfig.advancedDistributionHost}/${primaryVersion.file}`;
         } else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const storageConfig = await getTeamStorageConfigById(document.teamId);
returnData.file = `https://${storageConfig.advancedDistributionHost}/${primaryVersion.file}`;
} else {
const storageConfig = await getTeamStorageConfigById(document.teamId);
if (!storageConfig.advancedDistributionHost) {
return res.status(503).json({
message:
"Advanced Excel preview is not configured for this team.",
});
}
returnData.file = `https://${storageConfig.advancedDistributionHost}/${primaryVersion.file}`;
} else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/api/teams/`[teamId]/documents/[id]/preview-data.ts around lines 133 -
135, Guard construction of the preview URL by checking
storageConfig.advancedDistributionHost before building the string: in the
handler where getTeamStorageConfigById(document.teamId) is called, only set
returnData.file =
`https://${storageConfig.advancedDistributionHost}/${primaryVersion.file}` when
storageConfig?.advancedDistributionHost is truthy; otherwise fall back to a safe
alternative (e.g., leave returnData.file as primaryVersion.file or construct
using the standard storage host) to avoid producing "https://undefined/..." and
breaking previews.

returnData.file = primaryVersion.file;
}
returnData.numPages = 1;
}
// Non-advanced sheets: return 200 with advancedExcelEnabled=false so
// PreviewViewer renders its inline fallback instead of showing an error.
} else if (primaryVersion.type === "notion") {
// Notion documents - preview not supported
return res.status(400).json({
Expand Down
1 change: 1 addition & 0 deletions pages/documents/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export default function DocumentPage() {
key={"preview"}
documentId={prismaDocument.id}
primaryVersion={primaryVersion}
advancedExcelEnabled={prismaDocument.advancedExcelEnabled}
variant="outline"
size="default"
showTooltip={false}
Expand Down
Loading