From 6c9b464266e93a5f2a245f1f974dc6d3458867ab Mon Sep 17 00:00:00 2001 From: kelvinsuen Date: Thu, 26 Jun 2025 11:20:47 +0800 Subject: [PATCH] updated view PDF updated README --- .gitignore | 1 + README.md | 8 +- src/pages/client/ClientMaintainPage/index.js | 6 - .../client/ClientSearchPage/ClientTable.js | 14 ++ src/pages/pdf/index.js | 206 ++++++++++++------ src/utils/CommonFunction.js | 5 +- 6 files changed, 166 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index 4f9b01e..6d13147 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ build/Release # Dependency directories node_modules/ +/public/sdk jspm_packages/ # TypeScript v1 declaration files diff --git a/README.md b/README.md index 4837f3f..10c2038 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,10 @@ - Start the application by the following command: ``` npm start - ``` \ No newline at end of file + ``` + +## 3. Config the library + - Navigate to "LIONER-frontend\node_modules\pspdfkit\dist" + - Copy the folder "pspdfkit-lib" + - Create a new folder "sdk" in "LIONER-frontend\public" + - Paste the "pspdfkit-lib" inside "sdk" folder \ No newline at end of file diff --git a/src/pages/client/ClientMaintainPage/index.js b/src/pages/client/ClientMaintainPage/index.js index ade8878..86e480f 100644 --- a/src/pages/client/ClientMaintainPage/index.js +++ b/src/pages/client/ClientMaintainPage/index.js @@ -9,13 +9,7 @@ import * as React from "react"; import axios from "axios"; import {apiPath} from "../../../auth/utils"; import { - GET_EVENT_APPLICATION_PATH, GET_CLIENT_PATH, - GET_REMINDER_BEFORE, - GET_REMINDER_INTERVAL, - GET_REMINDER_LIMIT, - GET_REMINDER_LIMIT_MAX, - GET_SUB_DIVISION_COMBO_LIST, } from "../../../utils/ApiPathConst"; import LoadingComponent from "../../extra-pages/LoadingComponent"; import {useLocation, useParams} from "react-router-dom"; diff --git a/src/pages/client/ClientSearchPage/ClientTable.js b/src/pages/client/ClientSearchPage/ClientTable.js index ae864b1..7394bba 100644 --- a/src/pages/client/ClientSearchPage/ClientTable.js +++ b/src/pages/client/ClientSearchPage/ClientTable.js @@ -5,6 +5,7 @@ import { GridActionsCellItem, } from "@mui/x-data-grid"; import EditIcon from '@mui/icons-material/Edit'; +import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import {useContext, useEffect} from "react"; import {useNavigate} from "react-router-dom"; import {CustomNoRowsOverlay, dateComparator, getDateString} from "../../../utils/CommonFunction"; @@ -34,6 +35,10 @@ export default function ClientTable({recordList}) { navigate('/client/maintain/'+ id); }; + const handlePDFClick = () => () => { + navigate('/pdf'); + }; + const columns = [ { field: 'actions', @@ -54,6 +59,15 @@ export default function ClientTable({recordList}) { // disabled={'true'} // disabled={!ability.can('VIEW','DASHBOARD')} /> + } + label="Edit PDF" + className="textPrimary" + onClick={handlePDFClick()} + color="edit" + // disabled={'true'} + // disabled={!ability.can('VIEW','DASHBOARD')} + /> ] }, diff --git a/src/pages/pdf/index.js b/src/pages/pdf/index.js index 661985a..a12a2fa 100644 --- a/src/pages/pdf/index.js +++ b/src/pages/pdf/index.js @@ -1,11 +1,15 @@ -// src/App.js (Your 'pdfForm' page equivalent) import React, { useEffect, useRef, useState } from 'react'; -// import './App.css'; // For basic styling +import { Button, Grid } from '@mui/material'; +import { GeneralConfirmWindow } from "../../utils/CommonFunction"; import axios from 'axios'; import {apiPath} from "../../auth/utils"; import { - GET_PDF_PATH + GET_PDF_PATH, + POST_PDF_PATH } from "../../utils/ApiPathConst"; +import {LIONER_BUTTON_THEME} from "../../themes/colorConst"; +import {ThemeProvider} from "@emotion/react"; +import {useNavigate} from "react-router-dom"; // Import your chosen commercial PDF SDK (e.g., PSPDFKit) import PSPDFKit from 'pspdfkit'; @@ -14,74 +18,95 @@ function PDF() { const viewerRef = useRef(null); // Ref for the DOM element where PDF will render const instanceRef = useRef(null); // Ref for the PSPDFKit instance const [pdfLoaded, setPdfLoaded] = useState(false); + const [viewerLoaded, setViewerLoaded] = useState(false); const [template,setTemplate] = useState(); const [viewInstance,setViewInstance] = useState(); + const navigate = useNavigate() - useEffect(() => { - const loadPdfViewer = async () => { - if (document.getElementById(viewerRef)) { - // if (viewerRef.current) { - try { - //New try - axios.get(`${apiPath}${GET_PDF_PATH}`, { - responseType: 'arraybuffer', // Essential for binary data - }) - .then((response) => { - if (response.status === 200) { - setTemplate(response); - } - }) - .catch(error => { - console.log(error); - return false; - }); - // 1. Fetch the blank PDF template from your Spring Boot backend - // const response = await axios.get(`${apiPath}${GET_PDF_PATH}`, { - // responseType: 'arraybuffer', // Essential for binary data - // }); - const pdfBlob = new Blob(template, { type: 'application/pdf' }); - const pdfUrl = URL.createObjectURL(pdfBlob); - - // 2. Initialize the PDF SDK (e.g., PSPDFKit) - console.log(template); - - const instance = await PSPDFKit.load({ - // setViewInstance(await PSPDFKit.load({ - container: document.getElementById(viewerRef),//viewerRef.current, - document: pdfUrl, - // Remember to add your SDK license key if applicable - // licenseKey: "YOUR_PSPDFKIT_LICENSE_KEY", - baseUrl: `${process.env.PUBLIC_URL}/pspdfkit-lib/`//, // Path to SDK assets - // Enable form filling UI - // formDesignerViewMode: PSPDFKit.FormDesignerViewMode.Enabled - }); - // })); - - instanceRef.current = instance; + const loadPdfTemplate = async () => { + // if (!pdfLoaded) { + axios.get(`${apiPath}${GET_PDF_PATH}`, { + responseType: 'arraybuffer', // Essential for binary data + }) + .then((response) => { + if (response.status === 200) { + setTemplate(response.data); setPdfLoaded(true); + } + }) + .catch(error => { + console.log(error); + return false; + }); + // } + }; + + const loadPdfViewer = async () => {console.log(`PDF loaded = ${pdfLoaded}`); + if (pdfLoaded && viewerRef.current) { + try { + //New try + console.log(typeof(template)); + const pdfBlob = new Blob([template], { type: 'application/pdf' }); + const pdfUrl = URL.createObjectURL(pdfBlob); + + console.log('Template: '); + console.log(template.data); + console.log('URL: '); + console.log(pdfUrl); + console.log('Viewer: '); + console.log(viewerRef.current); + PSPDFKit.unload(viewerRef.current); + await PSPDFKit.load({//click into load + container: viewerRef.current, + // container: '#viewer', + document: pdfUrl, + // baseUrl: `./sdk/`, // Path to SDK assets + baseUrl: `http://localhost:3000/sdk/`, // Path to SDK + // baseUrl: `${window.location.protocol}//${window.location.host}/${import.meta.env.BASE_URL}`, + // baseUrl: `https://cdn.jsdelivr.net/npm/pspdfkit@VERSION/dist/`, // Path to SDK assets so this is work? + // baseUrl: `${process.env.PUBLIC_URL}/`, // Path to SDK assets + disableWebAssemblyStreaming: true, + initialViewState: new PSPDFKit.ViewState({ + sidebarMode: PSPDFKit.SidebarMode.THUMBNAILS + }) + }) + .then(instance => { + URL.revokeObjectURL(pdfUrl); + setViewInstance(instance); + console.log('instance: '); + console.log(instance); + setViewerLoaded(true); + }); - // 3. Clean up on component unmount - return () => { - if (instance) { - instance.unload(); // Unload SDK instance - } - URL.revokeObjectURL(pdfUrl); // Revoke the Blob URL - }; + // instanceRef.current = instance; - } catch (error) { - console.error('Error loading PDF:', error); - } + // 3. Clean up on component unmount + // return () => { + // if (instance) { + // instance.unload(); // Unload SDK instance + // } + // URL.revokeObjectURL(pdfUrl); // Revoke the Blob URL + // }; + + } catch (error) { + console.error('Error loading PDF:', error); } - }; + } + }; + useEffect(() => { + loadPdfTemplate(); + }, []); + + useEffect(() => { loadPdfViewer(); - }, []); // Empty dependency array means this runs once on mount + }, [viewerRef, pdfLoaded]); const handleSavePdf = async () => { - if (instanceRef.current) { + if (viewInstance.current) {console.log("tetes"); try { // Export the filled PDF from the SDK as an ArrayBuffer - const arrayBuffer = await instanceRef.current.exportPDF(); + const arrayBuffer = await viewInstance.current.exportPDF(); const filledPdfBlob = new Blob([arrayBuffer], { type: 'application/pdf' }); // Create FormData to send the file to Spring Boot @@ -89,7 +114,7 @@ function PDF() { formData.append('file', filledPdfBlob, 'filled_form.pdf'); // Send the filled PDF to your Spring Boot backend's save endpoint - const response = await axios.post('http://localhost:8090/api/pdf/saveFilled', formData, { + const response = await axios.post(`${apiPath}${POST_PDF_PATH}`, formData, { headers: { 'Content-Type': 'multipart/form-data' // Important for file uploads } @@ -104,17 +129,64 @@ function PDF() { }; const handlePrintPdf = () => { - if (instanceRef.current) { + if (viewInstance.current) { // Trigger the SDK's built-in print functionality - instanceRef.current.print(); + viewInstance.current.print(); } }; + // Confirmation Window // + const [isWindowOpen, setIsWindowOpen] = useState(false); + + const handleClose = () => { + setIsWindowOpen(false); + }; + + const handleBackClick = () => { + setIsWindowOpen(true); + }; + + const handleBack = () => { + navigate('/client'); + }; + return ( +
{/* This is your 'pdfForm' page */}
-

Fill and Manage Your PDF Form

- {pdfLoaded ? ( + + + + + + + + + + + + {/* {pdfLoaded ? (
) : (

Loading PDF viewer...

- )} + )} */}
+ ); } diff --git a/src/utils/CommonFunction.js b/src/utils/CommonFunction.js index 4d8c0b1..e2e2530 100644 --- a/src/utils/CommonFunction.js +++ b/src/utils/CommonFunction.js @@ -423,6 +423,9 @@ export function CustomNoRowsOverlay() { } export function GeneralConfirmWindow({ isWindowOpen, title, content, onNormalClose, onConfirmClose }) { + const formattedContent = content.split('\n').map((line, index) => ( + {line}
+ )); return ( - {content} + {formattedContent}