From 64dfa4b8416aba48524137516c908f4f00674f26 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Tue, 10 Dec 2024 22:21:00 +0000 Subject: [PATCH] Tweak additional files to integrate decryption and clean up js --- src/main/resources/static/js/fileInput.js | 2 +- .../resources/static/js/pages/add-image.js | 47 ++++++ .../static/js/pages/change-metadata.js | 150 +++++++++++++++++ src/main/resources/static/js/pages/crop.js | 159 ++++++++++++++++++ .../resources/static/js/pages/pdf-to-csv.js | 138 +++++++++++++++ src/main/resources/static/js/pages/sign.js | 2 - .../templates/convert/pdf-to-csv.html | 136 +-------------- src/main/resources/templates/crop.html | 158 +---------------- .../resources/templates/misc/add-image.html | 50 +----- .../templates/misc/change-metadata.html | 135 +-------------- src/main/resources/templates/overlay-pdf.html | 1 + 11 files changed, 501 insertions(+), 477 deletions(-) create mode 100644 src/main/resources/static/js/pages/add-image.js create mode 100644 src/main/resources/static/js/pages/change-metadata.js create mode 100644 src/main/resources/static/js/pages/crop.js create mode 100644 src/main/resources/static/js/pages/pdf-to-csv.js diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index 57010b6c6..63485c606 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -2,7 +2,6 @@ import FileIconFactory from './file-icon-factory.js'; import FileUtils from './file-utils.js'; import UUID from './uuid.js'; import {DecryptFile} from './DecryptFiles.js'; -const decryptFile = new DecryptFile(); let isScriptExecuted = false; if (!isScriptExecuted) { isScriptExecuted = true; @@ -123,6 +122,7 @@ function setupFileInput(chooser) { return decryptedFile; } catch (error) { console.error(`Error decrypting file: ${file.name}`, error); + if (!file.uniqueId) file.uniqueId = UUID.uuidv4(); return file; } }) diff --git a/src/main/resources/static/js/pages/add-image.js b/src/main/resources/static/js/pages/add-image.js new file mode 100644 index 000000000..5899b53f9 --- /dev/null +++ b/src/main/resources/static/js/pages/add-image.js @@ -0,0 +1,47 @@ +document.getElementById('download-pdf').addEventListener('click', async () => { + const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); + const modifiedPdfBytes = await modifiedPdf.save(); + const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = originalFileName + '_addedImage.pdf'; + link.click(); +}); +let originalFileName = ''; +document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { + const fileInput = event.target; + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + const file = allFiles[0]; + originalFileName = file.name.replace(/\.[^/.]+$/, ''); + const pdfData = await file.arrayBuffer(); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + const pdfDoc = await pdfjsLib.getDocument({data: pdfData}).promise; + await DraggableUtils.renderPage(pdfDoc, 0); + + document.querySelectorAll('.show-on-file-selected').forEach((el) => { + el.style.cssText = ''; + }); + } + }); +}); +document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('.show-on-file-selected').forEach((el) => { + el.style.cssText = 'display:none !important'; + }); +}); + +const imageUpload = document.querySelector('input[name=image-upload]'); +imageUpload.addEventListener('change', (e) => { + if (!e.target.files) { + return; + } + for (const imageFile of e.target.files) { + var reader = new FileReader(); + reader.readAsDataURL(imageFile); + reader.onloadend = function (e) { + DraggableUtils.createDraggableCanvasFromUrl(e.target.result); + }; + } +}); diff --git a/src/main/resources/static/js/pages/change-metadata.js b/src/main/resources/static/js/pages/change-metadata.js new file mode 100644 index 000000000..bdc5426b7 --- /dev/null +++ b/src/main/resources/static/js/pages/change-metadata.js @@ -0,0 +1,150 @@ +const deleteAllCheckbox = document.querySelector('#deleteAll'); +let inputs = document.querySelectorAll('input'); +const customMetadataDiv = document.getElementById('customMetadata'); +const otherMetadataEntriesDiv = document.getElementById('otherMetadataEntries'); + +deleteAllCheckbox.addEventListener('change', function (event) { + inputs.forEach((input) => { + // If it's the deleteAllCheckbox or any file input, skip + if (input === deleteAllCheckbox || input.type === 'file') { + return; + } + // Disable or enable based on the checkbox state + input.disabled = deleteAllCheckbox.checked; + }); +}); + +const customModeCheckbox = document.getElementById('customModeCheckbox'); +const addMetadataBtn = document.getElementById('addMetadataBtn'); +const customMetadataFormContainer = document.getElementById('customMetadataEntries'); +var count = 1; +const fileInput = document.querySelector('#fileInput-input'); +const authorInput = document.querySelector('#author'); +const creationDateInput = document.querySelector('#creationDate'); +const creatorInput = document.querySelector('#creator'); +const keywordsInput = document.querySelector('#keywords'); +const modificationDateInput = document.querySelector('#modificationDate'); +const producerInput = document.querySelector('#producer'); +const subjectInput = document.querySelector('#subject'); +const titleInput = document.querySelector('#title'); +const trappedInput = document.querySelector('#trapped'); +var lastPDFFileMeta = null; +var lastPDFFile = null; + +fileInput.addEventListener('change', async function () { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + const file = allFiles[0]; + while (otherMetadataEntriesDiv.firstChild) { + otherMetadataEntriesDiv.removeChild(otherMetadataEntriesDiv.firstChild); + } + while (customMetadataFormContainer.firstChild) { + customMetadataFormContainer.removeChild(customMetadataFormContainer.firstChild); + } + var url = URL.createObjectURL(file); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + const pdf = await pdfjsLib.getDocument(url).promise; + const pdfMetadata = await pdf.getMetadata(); + lastPDFFile = pdfMetadata?.info; + console.log(pdfMetadata); + if (!pdfMetadata?.info?.Custom || pdfMetadata?.info?.Custom.size == 0) { + customModeCheckbox.disabled = true; + customModeCheckbox.checked = false; + } else { + customModeCheckbox.disabled = false; + } + authorInput.value = pdfMetadata?.info?.Author; + creationDateInput.value = convertDateFormat(pdfMetadata?.info?.CreationDate); + creatorInput.value = pdfMetadata?.info?.Creator; + keywordsInput.value = pdfMetadata?.info?.Keywords; + modificationDateInput.value = convertDateFormat(pdfMetadata?.info?.ModDate); + producerInput.value = pdfMetadata?.info?.Producer; + subjectInput.value = pdfMetadata?.info?.Subject; + titleInput.value = pdfMetadata?.info?.Title; + console.log(pdfMetadata?.info); + const trappedValue = pdfMetadata?.info?.Trapped; + // Get all options in the select element + const options = trappedInput.options; + // Loop through all options to find the one with a matching value + for (let i = 0; i < options.length; i++) { + if (options[i].value === trappedValue) { + options[i].selected = true; + break; + } + } + addExtra(); + } + }); +}); + +addMetadataBtn.addEventListener('click', () => { + const keyInput = document.createElement('input'); + keyInput.type = 'text'; + keyInput.placeholder = 'Key'; + keyInput.className = 'form-control'; + keyInput.name = `allRequestParams[customKey${count}]`; + + const valueInput = document.createElement('input'); + valueInput.type = 'text'; + valueInput.placeholder = 'Value'; + valueInput.className = 'form-control'; + valueInput.name = `allRequestParams[customValue${count}]`; + count = count + 1; + + const formGroup = document.createElement('div'); + formGroup.className = 'mb-3'; + formGroup.appendChild(keyInput); + formGroup.appendChild(valueInput); + + customMetadataFormContainer.appendChild(formGroup); +}); +function convertDateFormat(dateTimeString) { + if (!dateTimeString || dateTimeString.length < 17) { + return dateTimeString; + } + + const year = dateTimeString.substring(2, 6); + const month = dateTimeString.substring(6, 8); + const day = dateTimeString.substring(8, 10); + const hour = dateTimeString.substring(10, 12); + const minute = dateTimeString.substring(12, 14); + const second = dateTimeString.substring(14, 16); + + return year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second; +} + +function addExtra() { + const event = document.getElementById('customModeCheckbox'); + if (event.checked && lastPDFFile.Custom != null) { + customMetadataDiv.style.display = 'block'; + for (const [key, value] of Object.entries(lastPDFFile.Custom)) { + if ( + key === 'Author' || + key === 'CreationDate' || + key === 'Creator' || + key === 'Keywords' || + key === 'ModDate' || + key === 'Producer' || + key === 'Subject' || + key === 'Title' || + key === 'Trapped' + ) { + continue; + } + const entryDiv = document.createElement('div'); + entryDiv.className = 'mb-3'; + entryDiv.innerHTML = `
`; + otherMetadataEntriesDiv.appendChild(entryDiv); + } + } else { + customMetadataDiv.style.display = 'none'; + while (otherMetadataEntriesDiv.firstChild) { + otherMetadataEntriesDiv.removeChild(otherMetadataEntriesDiv.firstChild); + } + } +} + +customModeCheckbox.addEventListener('change', (event) => { + addExtra(); +}); diff --git a/src/main/resources/static/js/pages/crop.js b/src/main/resources/static/js/pages/crop.js new file mode 100644 index 000000000..1854023a0 --- /dev/null +++ b/src/main/resources/static/js/pages/crop.js @@ -0,0 +1,159 @@ +let pdfCanvas = document.getElementById('cropPdfCanvas'); +let overlayCanvas = document.getElementById('overlayCanvas'); +let canvasesContainer = document.getElementById('canvasesContainer'); +canvasesContainer.style.display = 'none'; +let containerRect = canvasesContainer.getBoundingClientRect(); + +let context = pdfCanvas.getContext('2d'); +let overlayContext = overlayCanvas.getContext('2d'); + +overlayCanvas.width = pdfCanvas.width; +overlayCanvas.height = pdfCanvas.height; + +let isDrawing = false; // New flag to check if drawing is ongoing + +let cropForm = document.getElementById('cropForm'); +let fileInput = document.getElementById('fileInput-input'); +let xInput = document.getElementById('x'); +let yInput = document.getElementById('y'); +let widthInput = document.getElementById('width'); +let heightInput = document.getElementById('height'); + +let pdfDoc = null; +let currentPage = 1; +let totalPages = 0; + +let startX = 0; +let startY = 0; +let rectWidth = 0; +let rectHeight = 0; + +let pageScale = 1; // The scale which the pdf page renders +let timeId = null; // timeout id for resizing canvases event + +function renderPageFromFile(file) { + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } +} + +window.addEventListener('resize', function () { + clearTimeout(timeId); + + timeId = setTimeout(function () { + if (fileInput.files.length == 0) return; + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + pdfCanvas.width = containerRect.width; + pdfCanvas.height = containerRect.height; + + overlayCanvas.width = containerRect.width; + overlayCanvas.height = containerRect.height; + + let file = fileInput.files[0]; + renderPageFromFile(file); + }, 1000); +}); + +fileInput.addEventListener('change', function (e) { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + canvasesContainer.style.display = 'block'; // set for visual purposes + let file = allFiles[0]; + renderPageFromFile(file); + } + }); +}); + +cropForm.addEventListener('submit', function (e) { + if (xInput.value == '' && yInput.value == '' && widthInput.value == '' && heightInput.value == '') { + // Ορίστε συντεταγμένες για ολόκληρη την επιφάνεια του PDF + xInput.value = 0; + yInput.value = 0; + widthInput.value = containerRect.width; + heightInput.value = containerRect.height; + } +}); + +overlayCanvas.addEventListener('mousedown', function (e) { + // Clear previously drawn rectangle on the main canvas + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + renderPage(currentPage); // Re-render the PDF + + // Clear the overlay canvas to ensure old drawings are removed + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + startX = e.offsetX; + startY = e.offsetY; + isDrawing = true; +}); + +overlayCanvas.addEventListener('mousemove', function (e) { + if (!isDrawing) return; + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); // Clear previous rectangle + + rectWidth = e.offsetX - startX; + rectHeight = e.offsetY - startY; + overlayContext.strokeStyle = 'red'; + overlayContext.strokeRect(startX, startY, rectWidth, rectHeight); +}); + +overlayCanvas.addEventListener('mouseup', function (e) { + isDrawing = false; + + rectWidth = e.offsetX - startX; + rectHeight = e.offsetY - startY; + + let flippedY = pdfCanvas.height - e.offsetY; + + xInput.value = startX / pageScale; + yInput.value = flippedY / pageScale; + widthInput.value = rectWidth / pageScale; + heightInput.value = rectHeight / pageScale; + + // Draw the final rectangle on the main canvas + context.strokeStyle = 'red'; + context.strokeRect(startX, startY, rectWidth, rectHeight); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); // Clear the overlay +}); + +function renderPage(pageNumber) { + pdfDoc.getPage(pageNumber).then(function (page) { + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + pageScale = containerRect.width / page.getViewport({scale: 1}).width; // The new scale + + let viewport = page.getViewport({scale: containerRect.width / page.getViewport({scale: 1}).width}); + + canvasesContainer.width = viewport.width; + canvasesContainer.height = viewport.height; + + pdfCanvas.width = viewport.width; + pdfCanvas.height = viewport.height; + + overlayCanvas.width = viewport.width; // Match overlay canvas size with PDF canvas + overlayCanvas.height = viewport.height; + + let renderContext = {canvasContext: context, viewport: viewport}; + page.render(renderContext); + pdfCanvas.classList.add('shadow-canvas'); + }); +} diff --git a/src/main/resources/static/js/pages/pdf-to-csv.js b/src/main/resources/static/js/pages/pdf-to-csv.js new file mode 100644 index 000000000..6be3c2ed6 --- /dev/null +++ b/src/main/resources/static/js/pages/pdf-to-csv.js @@ -0,0 +1,138 @@ +let pdfCanvas = document.getElementById('cropPdfCanvas'); +let overlayCanvas = document.getElementById('overlayCanvas'); +let canvasesContainer = document.getElementById('canvasesContainer'); +canvasesContainer.style.display = 'none'; +// let paginationBtnContainer = ; + +let context = pdfCanvas.getContext('2d'); +let overlayContext = overlayCanvas.getContext('2d'); + +let btn1Object = document.getElementById('previous-page-btn'); +let btn2Object = document.getElementById('next-page-btn'); +overlayCanvas.width = pdfCanvas.width; +overlayCanvas.height = pdfCanvas.height; + +let fileInput = document.getElementById('fileInput-input'); + +let file; + +let pdfDoc = null; +let pageId = document.getElementById('pageId'); +let currentPage = 1; +let totalPages = 0; + +let startX = 0; +let startY = 0; +let rectWidth = 0; +let rectHeight = 0; + +let timeId = null; // timeout id for resizing canvases event + +btn1Object.addEventListener('click', function (e) { + if (currentPage !== 1) { + currentPage = currentPage - 1; + pageId.value = currentPage; + + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } + } +}); + +btn2Object.addEventListener('click', function (e) { + if (currentPage !== totalPages) { + currentPage = currentPage + 1; + pageId.value = currentPage; + + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } + } +}); + +function renderPageFromFile(file) { + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + pageId.value = currentPage; + }; + reader.readAsArrayBuffer(file); + document.getElementById('pagination-button-container').style.display = 'flex'; + document.getElementById('instruction-text').style.display = 'block'; + } +} + +window.addEventListener('resize', function () { + clearTimeout(timeId); + timeId = setTimeout(function () { + if (fileInput.files.length == 0) return; + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + pdfCanvas.width = containerRect.width; + pdfCanvas.height = containerRect.height; + + overlayCanvas.width = containerRect.width; + overlayCanvas.height = containerRect.height; + + let file = fileInput.files[0]; + renderPageFromFile(file); + }, 1000); +}); + +fileInput.addEventListener('change', function (e) { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + canvasesContainer.style.display = 'block'; // set for visual purposes + file = e.target.files[0]; + renderPageFromFile(file); + } + }); +}); + +function renderPage(pageNumber) { + pdfDoc.getPage(pageNumber).then(function (page) { + let viewport = page.getViewport({scale: 1.0}); + pdfCanvas.width = viewport.width; + pdfCanvas.height = viewport.height; + + overlayCanvas.width = viewport.width; // Match overlay canvas size with PDF canvas + overlayCanvas.height = viewport.height; + + let renderContext = {canvasContext: context, viewport: viewport}; + page.render(renderContext); + pdfCanvas.classList.add('shadow-canvas'); + }); +} diff --git a/src/main/resources/static/js/pages/sign.js b/src/main/resources/static/js/pages/sign.js index 411fabf49..8d45c9697 100644 --- a/src/main/resources/static/js/pages/sign.js +++ b/src/main/resources/static/js/pages/sign.js @@ -52,8 +52,6 @@ function addSignatureFromPreview() { let originalFileName = ''; document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { const fileInput = event.target; - - // Wait for the second function to complete fileInput.addEventListener('file-input-change', async (e) => { const {allFiles} = e.detail; if (allFiles && allFiles.length > 0) { diff --git a/src/main/resources/templates/convert/pdf-to-csv.html b/src/main/resources/templates/convert/pdf-to-csv.html index b3dfc09cd..976837340 100644 --- a/src/main/resources/templates/convert/pdf-to-csv.html +++ b/src/main/resources/templates/convert/pdf-to-csv.html @@ -34,140 +34,8 @@ - + diff --git a/src/main/resources/templates/crop.html b/src/main/resources/templates/crop.html index e606fded5..5262f0f59 100644 --- a/src/main/resources/templates/crop.html +++ b/src/main/resources/templates/crop.html @@ -32,163 +32,7 @@ - + diff --git a/src/main/resources/templates/misc/add-image.html b/src/main/resources/templates/misc/add-image.html index 947185a73..6bca8ee7a 100644 --- a/src/main/resources/templates/misc/add-image.html +++ b/src/main/resources/templates/misc/add-image.html @@ -22,46 +22,9 @@
- - +
-
@@ -93,17 +56,6 @@
- diff --git a/src/main/resources/templates/misc/change-metadata.html b/src/main/resources/templates/misc/change-metadata.html index 50ba318bf..2aaa47e9a 100644 --- a/src/main/resources/templates/misc/change-metadata.html +++ b/src/main/resources/templates/misc/change-metadata.html @@ -85,140 +85,7 @@
- diff --git a/src/main/resources/templates/overlay-pdf.html b/src/main/resources/templates/overlay-pdf.html index e92e4cb08..616e3343a 100644 --- a/src/main/resources/templates/overlay-pdf.html +++ b/src/main/resources/templates/overlay-pdf.html @@ -2,6 +2,7 @@ +