Files
zeekay caad90bc04 rip: enterprise dirs + paywalls — full AGPL, no commercial-license code
Drop the dual-licensed `ee/` tree entirely. All features previously
locked behind the Hanzo Dataroom Commercial License are now part of the
AGPL-3.0 core and freely available — custom domains, branded viewing,
advanced analytics, watermarks, access controls, Q&A, AI vector stores,
workflows, SAML SSO, dataroom invitations, conversations, templates.

Layout changes:
* `ee/features/{ai,conversations,workflows,permissions,storage,templates,
  dataroom-invitations,access-notifications,security,conversions}/` →
  `features/<name>/` (AGPL).
* `ee/limits/` → `lib/billing/limits/` with every plan resolving to an
  unlimited profile (no users/links/documents/domains/datarooms cap,
  conversations and watermarks always on).
* `ee/stripe/` → `lib/billing/legacy/` (already a compat shim over
  `@hanzoai/commerce`; renewal-reminder webhook is now a no-op).
* `ee/features/billing/cancellation/` deleted. Pause/unpause/cancel/
  retention routes now compile against `lib/billing/cancellation.ts`
  stubs that return 410 Gone; `isTeamPaused`/`isTeamPausedById` in
  `lib/billing/paused.ts` always report active. `CancellationModal` is
  a no-op shim in `components/billing/`.
* `app/(ee)/api/*` route group folded into `app/api/*` (SAML auth,
  SCIM, AI chat, workflows, FAQ, link-upload).

Build: `npm run build` green.
2026-06-07 11:46:48 -07:00

248 lines
8.3 KiB
TypeScript

import dynamic from "next/dynamic";
import { ViewerChatPanel } from "@/features/ai/components/viewer-chat-panel";
import {
ViewerChatLayout,
ViewerChatProvider,
} from "@/features/ai/components/viewer-chat-provider";
import { ViewerChatToggle } from "@/features/ai/components/viewer-chat-toggle";
import {
Brand,
DataroomBrand,
Document,
DocumentVersion,
} from "@prisma/client";
import { ExtendedRecordMap } from "notion-types";
import {
LinkWithDataroomDocument,
LinkWithDocument,
NotionTheme,
WatermarkConfig,
} from "@/lib/types";
import { useMediaQuery } from "@/lib/utils/use-media-query";
import { DEFAULT_DOCUMENT_VIEW_TYPE } from "@/components/view/document-view";
import { NotionPage } from "@/components/view/viewer/notion-page";
import PDFViewer from "@/components/view/viewer/pdf-default-viewer";
import { DEFAULT_DATAROOM_DOCUMENT_VIEW_TYPE } from "./dataroom/dataroom-document-view";
import LinkPreview from "./link-preview";
import { TNavData } from "./nav";
import AdvancedExcelViewer from "./viewer/advanced-excel-viewer";
import DownloadOnlyViewer from "./viewer/download-only-viewer";
import ImageViewer from "./viewer/image-viewer";
import PagesHorizontalViewer from "./viewer/pages-horizontal-viewer";
import PagesVerticalViewer from "./viewer/pages-vertical-viewer";
import VideoViewer from "./viewer/video-viewer";
const ExcelViewer = dynamic(
() => import("@/components/view/viewer/excel-viewer"),
{ ssr: false },
);
export type TViewDocumentData = Document & {
versions: DocumentVersion[];
};
const isDownloadAllowed = (
canDownload: boolean | undefined,
linkAllowDownload: boolean | undefined,
): boolean => {
if (canDownload === false) return false;
return !!linkAllowDownload;
};
export default function ViewData({
viewData,
link,
document,
notionData,
brand,
showPoweredByBanner,
showAccountCreationSlide,
useAdvancedExcelViewer,
viewerEmail,
dataroomId,
canDownload,
annotationsEnabled,
textSelectionEnabled,
}: {
viewData: DEFAULT_DOCUMENT_VIEW_TYPE | DEFAULT_DATAROOM_DOCUMENT_VIEW_TYPE;
link: LinkWithDocument | LinkWithDataroomDocument;
document: TViewDocumentData;
notionData?: {
rootNotionPageId: string | null;
recordMap: ExtendedRecordMap | null;
theme: NotionTheme | null;
};
brand?: Partial<Brand> | Partial<DataroomBrand> | null;
showPoweredByBanner?: boolean;
showAccountCreationSlide?: boolean;
useAdvancedExcelViewer?: boolean;
viewerEmail?: string;
dataroomId?: string;
canDownload?: boolean;
annotationsEnabled?: boolean;
textSelectionEnabled?: boolean;
}) {
const { isMobile } = useMediaQuery();
const navData: TNavData = {
viewId: viewData.viewId,
isPreview: viewData.isPreview,
linkId: link.id,
brand: brand,
viewerId: "viewerId" in viewData ? viewData.viewerId : undefined,
isMobile: isMobile,
isDataroom: !!dataroomId,
documentId: document.id,
dataroomId: dataroomId,
conversationsEnabled:
!!dataroomId &&
("conversationsEnabled" in viewData
? viewData.conversationsEnabled
: false),
allowDownload:
document.downloadOnly ||
isDownloadAllowed(canDownload, link.allowDownload ?? false),
isTeamMember: viewData.isTeamMember,
annotationsFeatureEnabled: annotationsEnabled,
};
// Check if agents are enabled (returned from views API after access is granted)
const agentsEnabled =
"agentsEnabled" in viewData ? viewData.agentsEnabled : false;
// Determine dataroom name if applicable
const dataroomName =
dataroomId && "dataroomName" in viewData
? viewData.dataroomName
: undefined;
return (
<ViewerChatProvider
enabled={agentsEnabled}
documentId={document.id}
documentName={document.name}
dataroomId={dataroomId}
dataroomName={dataroomName}
linkId={link.id}
viewId={viewData.viewId}
viewerId={"viewerId" in viewData ? viewData.viewerId : undefined}
>
<ViewerChatLayout>
{notionData?.recordMap ? (
<NotionPage
recordMap={notionData.recordMap}
versionNumber={document.versions[0].versionNumber}
theme={notionData.theme}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
textSelectionEnabled={textSelectionEnabled ?? false}
navData={navData}
/>
) : viewData.fileType === "link" ? (
<LinkPreview
linkUrl={viewData.file || document.versions[0]?.file || ""}
linkName={document.name}
versionNumber={document.versions[0]?.versionNumber || 1}
navData={navData}
/>
) : document.downloadOnly ? (
<DownloadOnlyViewer
versionNumber={document.versions[0].versionNumber}
documentName={document.name}
navData={navData}
/>
) : viewData.fileType === "sheet" && viewData.sheetData ? (
<ExcelViewer
versionNumber={document.versions[0].versionNumber}
sheetData={viewData.sheetData}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
navData={navData}
/>
) : viewData.fileType === "sheet" && useAdvancedExcelViewer ? (
<AdvancedExcelViewer
file={viewData.file!}
versionNumber={document.versions[0].versionNumber}
navData={navData}
/>
) : viewData.fileType === "image" ? (
<ImageViewer
file={viewData.file!}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
versionNumber={document.versions[0].versionNumber}
showPoweredByBanner={showPoweredByBanner}
viewerEmail={viewerEmail}
watermarkConfig={
link.enableWatermark
? (link.watermarkConfig as WatermarkConfig)
: null
}
ipAddress={viewData.ipAddress}
linkName={link.name ?? `Link #${link.id.slice(-5)}`}
navData={navData}
/>
) : viewData.pages && !document.versions[0].isVertical ? (
<PagesHorizontalViewer
pages={viewData.pages}
feedbackEnabled={link.enableFeedback!}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
versionNumber={document.versions[0].versionNumber}
showPoweredByBanner={showPoweredByBanner}
showAccountCreationSlide={showAccountCreationSlide}
enableQuestion={link.enableQuestion}
feedback={link.feedback}
viewerEmail={viewerEmail}
watermarkConfig={
link.enableWatermark
? (link.watermarkConfig as WatermarkConfig)
: null
}
ipAddress={viewData.ipAddress}
linkName={link.name ?? `Link #${link.id.slice(-5)}`}
navData={navData}
/>
) : viewData.pages && document.versions[0].isVertical ? (
<PagesVerticalViewer
pages={viewData.pages}
feedbackEnabled={link.enableFeedback!}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
versionNumber={document.versions[0].versionNumber}
showPoweredByBanner={showPoweredByBanner}
enableQuestion={link.enableQuestion}
feedback={link.feedback}
viewerEmail={viewerEmail}
watermarkConfig={
link.enableWatermark
? (link.watermarkConfig as WatermarkConfig)
: null
}
ipAddress={viewData.ipAddress}
linkName={link.name ?? `Link #${link.id.slice(-5)}`}
navData={navData}
/>
) : viewData.fileType === "video" ? (
<VideoViewer
file={viewData.file!}
screenshotProtectionEnabled={link.enableScreenshotProtection!}
versionNumber={document.versions[0].versionNumber}
navData={navData}
/>
) : (
<PDFViewer
file={viewData.file}
name={document.name}
versionNumber={document.versions[0].versionNumber}
navData={navData}
/>
)}
</ViewerChatLayout>
{/* AI Chat Components */}
<ViewerChatPanel />
<ViewerChatToggle />
</ViewerChatProvider>
);
}