feat: add sheet viewer
- MIT licensed handsontable v6.2.2
This commit is contained in:
+3
-1
@@ -2,4 +2,6 @@ node_modules/
|
||||
.next/
|
||||
.react-email/
|
||||
.vercel/
|
||||
.github/
|
||||
.github/
|
||||
*.min.js
|
||||
*.min.css
|
||||
@@ -3,13 +3,13 @@ import { ExtendedRecordMap } from "notion-types";
|
||||
|
||||
import { NotionPage } from "@/components/NotionPage";
|
||||
import PDFViewer from "@/components/view/PDFViewer";
|
||||
import PagesViewer from "@/components/view/PagesViewer";
|
||||
import PagesViewerNew from "@/components/view/PagesViewerNew";
|
||||
import { DEFAULT_DOCUMENT_VIEW_TYPE } from "@/components/view/document-view";
|
||||
import Nav from "@/components/view/nav";
|
||||
import { ExcelViewer } from "@/components/view/viewer/excel-viewer";
|
||||
|
||||
import { LinkWithDocument } from "@/lib/types";
|
||||
|
||||
import PagesViewerNew from "./PagesViewerNew";
|
||||
import { DEFAULT_DOCUMENT_VIEW_TYPE } from "./document-view";
|
||||
|
||||
export default function ViewData({
|
||||
viewData,
|
||||
link,
|
||||
@@ -38,6 +38,19 @@ export default function ViewData({
|
||||
versionNumber={document.versions[0].versionNumber}
|
||||
brand={brand}
|
||||
/>
|
||||
) : viewData.sheetData ? (
|
||||
<>
|
||||
<Nav
|
||||
pageNumber={1}
|
||||
brand={brand}
|
||||
viewId={viewData.viewId}
|
||||
linkId={link.id}
|
||||
/>
|
||||
<ExcelViewer
|
||||
columns={viewData.sheetData.columnData!}
|
||||
data={viewData.sheetData.rowData!}
|
||||
/>
|
||||
</>
|
||||
) : viewData.pages ? (
|
||||
<PagesViewerNew
|
||||
pages={viewData.pages}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
import "@/public/vendor/handsontable/handsontable.full.min.css";
|
||||
|
||||
// Define the type for the JSON data
|
||||
type SheetData = { [key: string]: any };
|
||||
|
||||
export const ExcelViewer = ({
|
||||
columns,
|
||||
data,
|
||||
}: {
|
||||
columns: string[];
|
||||
data: SheetData[];
|
||||
}) => {
|
||||
const [availableWidth, setAvailableWidth] = useState<number>(200);
|
||||
const [availableHeight, setAvailableHeight] = useState<number>(200);
|
||||
const [handsontableLoaded, setHandsontableLoaded] = useState<boolean>(true);
|
||||
|
||||
const hotRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
// @ts-ignore
|
||||
const hotInstanceRef = useRef<Handsontable | null>(null);
|
||||
|
||||
const calculateSize = () => {
|
||||
if (containerRef.current) {
|
||||
const offset = containerRef.current.getBoundingClientRect();
|
||||
setAvailableWidth(Math.max(offset.width - 60, 200));
|
||||
setAvailableHeight(Math.max(offset.height - 10, 200));
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
calculateSize();
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
calculateSize();
|
||||
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (handsontableLoaded && data.length && columns.length) {
|
||||
if (hotInstanceRef.current) {
|
||||
hotInstanceRef.current.destroy();
|
||||
}
|
||||
|
||||
console.log("data", data);
|
||||
console.log("columns", columns);
|
||||
|
||||
// @ts-ignore
|
||||
hotInstanceRef.current = new Handsontable(hotRef.current!, {
|
||||
data: data,
|
||||
readOnly: true,
|
||||
disableVisualSelection: true,
|
||||
comments: false,
|
||||
contextMenu: false,
|
||||
colHeaders: columns,
|
||||
rowHeaders: true,
|
||||
manualColumnResize: true,
|
||||
width: availableWidth,
|
||||
height: availableHeight,
|
||||
rowHeights: 23,
|
||||
stretchH: "none",
|
||||
viewportRowRenderingOffset: 10,
|
||||
viewportColumnRenderingOffset: 2,
|
||||
readOnlyCellClassName: "",
|
||||
// modifyColWidth: (width: number) => {
|
||||
// if (width > 300) {
|
||||
// return 300;
|
||||
// }
|
||||
// },
|
||||
});
|
||||
}
|
||||
}, [handsontableLoaded, data, columns, availableHeight, availableWidth]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{ height: "calc(100vh - 64px)" }}
|
||||
className="flex h-screen items-center justify-center"
|
||||
ref={containerRef}
|
||||
>
|
||||
<div ref={hotRef}></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
+1
-1
@@ -26,7 +26,7 @@ export const config = {
|
||||
* 4. /_vercel (Vercel internals)
|
||||
* 5. /favicon.ico, /sitemap.xml (static files)
|
||||
*/
|
||||
"/((?!api/|_next/|_static|_icons|_vercel|favicon.ico|sitemap.xml).*)",
|
||||
"/((?!api/|_next/|_static|vendor|_icons|_vercel|favicon.ico|sitemap.xml).*)",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
+7
-1
@@ -1,9 +1,15 @@
|
||||
import { Head, Html, Main, NextScript } from "next/document";
|
||||
import Script from "next/script";
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en" className="h-full bg-background" suppressHydrationWarning>
|
||||
<Head />
|
||||
<Head>
|
||||
<Script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/6.2.2/handsontable.full.min.js"
|
||||
strategy="beforeInteractive"
|
||||
/>
|
||||
</Head>
|
||||
<body className="h-full">
|
||||
<Main />
|
||||
<NextScript />
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user