feat: add sheet viewer

- MIT licensed handsontable v6.2.2
This commit is contained in:
Marc Seitz
2024-05-22 18:46:55 +02:00
parent 26f1e46e17
commit 10f7af4709
7 changed files with 195 additions and 7 deletions
+3 -1
View File
@@ -2,4 +2,6 @@ node_modules/
.next/
.react-email/
.vercel/
.github/
.github/
*.min.js
*.min.css
+17 -4
View File
@@ -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}
+89
View File
@@ -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
View File
@@ -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
View File
@@ -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