From 45c966939388172c25941b4307b14a557a82ba75 Mon Sep 17 00:00:00 2001 From: ske087 Date: Wed, 7 May 2025 16:38:40 +0300 Subject: [PATCH] updated template creation --- py_app/app/static/pdfjs/pdf.js | 203 +++++++++++++++++++++ py_app/app/static/pdfjs/pdf.worker.js | 29 +++ py_app/app/static/script.js | 212 ++++++++-------------- py_app/app/static/style.css | 31 ++++ py_app/app/templates/create_template.html | 29 ++- 5 files changed, 362 insertions(+), 142 deletions(-) create mode 100644 py_app/app/static/pdfjs/pdf.js create mode 100644 py_app/app/static/pdfjs/pdf.worker.js diff --git a/py_app/app/static/pdfjs/pdf.js b/py_app/app/static/pdfjs/pdf.js new file mode 100644 index 0000000..d707b01 --- /dev/null +++ b/py_app/app/static/pdfjs/pdf.js @@ -0,0 +1,203 @@ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// eslint-disable-next-line max-len +/** @typedef {import("./display/api").OnProgressParameters} OnProgressParameters */ +// eslint-disable-next-line max-len +/** @typedef {import("./display/api").PDFDocumentLoadingTask} PDFDocumentLoadingTask */ +/** @typedef {import("./display/api").PDFDocumentProxy} PDFDocumentProxy */ +/** @typedef {import("./display/api").PDFPageProxy} PDFPageProxy */ +/** @typedef {import("./display/api").RenderTask} RenderTask */ +/** @typedef {import("./display/display_utils").PageViewport} PageViewport */ + +import { + AbortException, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationMode, + AnnotationType, + createValidAbsoluteUrl, + FeatureTest, + getUuid, + ImageKind, + InvalidPDFException, + MathClamp, + normalizeUnicode, + OPS, + PasswordResponses, + PermissionFlag, + ResponseException, + shadow, + updateUrlHash, + Util, + VerbosityLevel, +} from "./shared/util.js"; +import { + build, + getDocument, + isValidExplicitDest, + PDFDataRangeTransport, + PDFWorker, + version, +} from "./display/api.js"; +import { + fetchData, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getXfaPageViewport, + isDataScheme, + isPdfFile, + noContextMenu, + OutputScale, + PDFDateString, + PixelsPerInch, + RenderingCancelledException, + setLayerDimensions, + stopEvent, + SupportedImageMimeTypes, +} from "./display/display_utils.js"; +import { AnnotationEditorLayer } from "./display/editor/annotation_editor_layer.js"; +import { AnnotationEditorUIManager } from "./display/editor/tools.js"; +import { AnnotationLayer } from "./display/annotation_layer.js"; +import { ColorPicker } from "./display/editor/color_picker.js"; +import { DOMSVGFactory } from "./display/svg_factory.js"; +import { DrawLayer } from "./display/draw_layer.js"; +import { GlobalWorkerOptions } from "./display/worker_options.js"; +import { HighlightOutliner } from "./display/editor/drawers/highlight.js"; +import { SignatureExtractor } from "./display/editor/drawers/signaturedraw.js"; +import { TextLayer } from "./display/text_layer.js"; +import { TouchManager } from "./display/touch_manager.js"; +import { XfaLayer } from "./display/xfa_layer.js"; + +/* eslint-disable-next-line no-unused-vars */ +const pdfjsVersion = + typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_VERSION") : void 0; +/* eslint-disable-next-line no-unused-vars */ +const pdfjsBuild = + typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_BUILD") : void 0; + +if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING || GENERIC")) { + globalThis.pdfjsTestingUtils = { + HighlightOutliner, + }; +} + +globalThis.pdfjsLib = { + AbortException, + AnnotationEditorLayer, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationEditorUIManager, + AnnotationLayer, + AnnotationMode, + AnnotationType, + build, + ColorPicker, + createValidAbsoluteUrl, + DOMSVGFactory, + DrawLayer, + FeatureTest, + fetchData, + getDocument, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getUuid, + getXfaPageViewport, + GlobalWorkerOptions, + ImageKind, + InvalidPDFException, + isDataScheme, + isPdfFile, + isValidExplicitDest, + MathClamp, + noContextMenu, + normalizeUnicode, + OPS, + OutputScale, + PasswordResponses, + PDFDataRangeTransport, + PDFDateString, + PDFWorker, + PermissionFlag, + PixelsPerInch, + RenderingCancelledException, + ResponseException, + setLayerDimensions, + shadow, + SignatureExtractor, + stopEvent, + SupportedImageMimeTypes, + TextLayer, + TouchManager, + updateUrlHash, + Util, + VerbosityLevel, + version, + XfaLayer, +}; + +export { + AbortException, + AnnotationEditorLayer, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationEditorUIManager, + AnnotationLayer, + AnnotationMode, + AnnotationType, + build, + ColorPicker, + createValidAbsoluteUrl, + DOMSVGFactory, + DrawLayer, + FeatureTest, + fetchData, + getDocument, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getUuid, + getXfaPageViewport, + GlobalWorkerOptions, + ImageKind, + InvalidPDFException, + isDataScheme, + isPdfFile, + isValidExplicitDest, + MathClamp, + noContextMenu, + normalizeUnicode, + OPS, + OutputScale, + PasswordResponses, + PDFDataRangeTransport, + PDFDateString, + PDFWorker, + PermissionFlag, + PixelsPerInch, + RenderingCancelledException, + ResponseException, + setLayerDimensions, + shadow, + SignatureExtractor, + stopEvent, + SupportedImageMimeTypes, + TextLayer, + TouchManager, + updateUrlHash, + Util, + VerbosityLevel, + version, + XfaLayer, +}; diff --git a/py_app/app/static/pdfjs/pdf.worker.js b/py_app/app/static/pdfjs/pdf.worker.js new file mode 100644 index 0000000..5d6bdf0 --- /dev/null +++ b/py_app/app/static/pdfjs/pdf.worker.js @@ -0,0 +1,29 @@ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { WorkerMessageHandler } from "./core/worker.js"; + +/* eslint-disable-next-line no-unused-vars */ +const pdfjsVersion = + typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_VERSION") : void 0; +/* eslint-disable-next-line no-unused-vars */ +const pdfjsBuild = + typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_BUILD") : void 0; + +globalThis.pdfjsWorker = { + WorkerMessageHandler, +}; + +export { WorkerMessageHandler }; diff --git a/py_app/app/static/script.js b/py_app/app/static/script.js index df51ff9..c18d610 100644 --- a/py_app/app/static/script.js +++ b/py_app/app/static/script.js @@ -193,153 +193,95 @@ document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => { const setDimensionsBtn = document.getElementById('set-dimensions-btn'); - const getTablesBtn = document.getElementById('get-tables-btn'); - const tablesContainer = document.getElementById('tables-container'); - const columnsContainer = document.getElementById('columns-container'); const labelPreview = document.getElementById('label-preview'); - const saveTemplateBtn = document.getElementById('save-template-btn'); - // Handle setting dimensions + // Handle setting label dimensions setDimensionsBtn.addEventListener('click', () => { - const width = document.getElementById('label-width').value; - const height = document.getElementById('label-height').value; + const widthInput = document.getElementById('label-width').value; + const heightInput = document.getElementById('label-height').value; - if (width && height) { - alert(`Label dimensions set to ${width}mm x ${height}mm.`); - } else { - alert('Please enter valid dimensions.'); + if (!widthInput || !heightInput) { + alert('Please enter valid dimensions for width and height.'); + return; } + + // Convert mm to pixels (1 mm = 3.779528 pixels) + const widthPixels = parseFloat(widthInput) * 3.779528; + const heightPixels = parseFloat(heightInput) * 3.779528; + + // Set the size of the label container + labelPreview.style.width = `${widthPixels}px`; + labelPreview.style.height = `${heightPixels}px`; + + alert(`Label dimensions set to ${widthPixels.toFixed(2)}px x ${heightPixels.toFixed(2)}px.`); + }); +}); +document.addEventListener('DOMContentLoaded', () => { + const labelPreview = document.getElementById('label-preview'); + const addFieldButtons = document.querySelectorAll('.add-field-btn'); + + // Add fields dynamically + addFieldButtons.forEach(button => { + button.addEventListener('click', () => { + const fieldType = button.getAttribute('data-type'); + addFieldToPreview(fieldType); + }); }); - // Handle fetching database tables - getTablesBtn.addEventListener('click', () => { - fetch('/get_tables') - .then(response => response.json()) - .then(data => { - tablesContainer.innerHTML = '

Select a Table:

'; - data.tables.forEach(table => { - const button = document.createElement('button'); - button.textContent = table; - button.classList.add('btn'); - button.addEventListener('click', () => fetchColumns(table)); - tablesContainer.appendChild(button); - }); - }) - .catch(error => console.error('Error fetching tables:', error)); - }); + // Function to add a field to the preview + function addFieldToPreview(type) { + const field = document.createElement('div'); + field.classList.add('draggable-field'); + field.setAttribute('draggable', 'true'); + field.style.position = 'absolute'; + field.style.top = '10px'; + field.style.left = '10px'; - // Fetch columns for a selected table - function fetchColumns(table) { - fetch(`/get_columns?table=${table}`) - .then(response => response.json()) - .then(data => { - columnsContainer.innerHTML = '

Select Columns:

'; - data.columns.forEach(column => { - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = column; - checkbox.id = `column-${column}`; - const label = document.createElement('label'); - label.textContent = column; - label.htmlFor = `column-${column}`; - columnsContainer.appendChild(checkbox); - columnsContainer.appendChild(label); - columnsContainer.appendChild(document.createElement('br')); + switch (type) { + case 'text-label': + field.textContent = 'Text Label'; + field.style.fontSize = '14px'; + break; + case 'text-input': + field.innerHTML = ''; + break; + case 'barcode': + field.textContent = 'Barcode Box'; + field.style.border = '1px dashed #000'; + field.style.width = '100px'; + field.style.height = '50px'; + break; + case 'qrcode': + field.textContent = 'QR Code Box'; + field.style.border = '1px dashed #000'; + field.style.width = '50px'; + field.style.height = '50px'; + break; + } - // Update label preview on checkbox change - checkbox.addEventListener('change', updateLabelPreview); - }); - }) - .catch(error => console.error('Error fetching columns:', error)); + labelPreview.appendChild(field); + + // Make the field draggable + makeFieldDraggable(field); } - // Update the label preview - function updateLabelPreview() { - const selectedColumns = Array.from(columnsContainer.querySelectorAll('input[type="checkbox"]:checked')) - .map(checkbox => checkbox.value); + // Function to make a field draggable + function makeFieldDraggable(field) { + field.addEventListener('dragstart', (e) => { + e.dataTransfer.setData('text/plain', null); + field.classList.add('dragging'); + }); - labelPreview.innerHTML = '

Label Preview:

'; - selectedColumns.forEach(column => { - const div = document.createElement('div'); - div.textContent = column; - labelPreview.appendChild(div); + field.addEventListener('dragend', () => { + field.classList.remove('dragging'); + }); + + labelPreview.addEventListener('dragover', (e) => { + e.preventDefault(); + const draggingField = document.querySelector('.dragging'); + const rect = labelPreview.getBoundingClientRect(); + draggingField.style.left = `${e.clientX - rect.left}px`; + draggingField.style.top = `${e.clientY - rect.top}px`; }); } - - // Handle saving the template - saveTemplateBtn.addEventListener('click', () => { - const selectedColumns = Array.from(columnsContainer.querySelectorAll('input[type="checkbox"]:checked')) - .map(checkbox => checkbox.value); - - if (selectedColumns.length === 0) { - alert('Please select at least one column for the label.'); - return; - } - - const width = document.getElementById('label-width').value; - const height = document.getElementById('label-height').value; - - if (!width || !height) { - alert('Please set the label dimensions.'); - return; - } - - const templateData = { - width, - height, - columns: selectedColumns - }; - - fetch('/save_template', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(templateData) - }) - .then(response => response.json()) - .then(data => { - alert(data.message); - }) - .catch(error => console.error('Error saving template:', error)); - }); - - document.getElementById('generate-pdf-btn').addEventListener('click', () => { - const width = document.getElementById('label-width').value; - const height = document.getElementById('label-height').value; - const selectedColumns = Array.from(document.querySelectorAll('#columns-container input[type="checkbox"]:checked')) - .map(checkbox => checkbox.value); - - if (!width || !height || selectedColumns.length === 0) { - alert('Please set dimensions and select at least one column.'); - return; - } - - const data = { - width: parseFloat(width), - height: parseFloat(height), - columns: selectedColumns - }; - - fetch('/generate_pdf', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(data) - }) - .then(response => response.json()) - .then(result => { - alert(result.message); - console.log('PDF Path:', result.pdf_path); - - // Provide a link to download the PDF - const downloadLink = document.createElement('a'); - downloadLink.href = result.pdf_path; - downloadLink.textContent = 'Download Generated PDF'; - downloadLink.target = '_blank'; - document.getElementById('label-preview').appendChild(downloadLink); - }) - .catch(error => console.error('Error generating PDF:', error)); - }); }); \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index 583ab04..951f41f 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -690,4 +690,35 @@ body.dark-mode .export-description { .go-to-main-etichete-btn:hover { background-color: #218838; /* Darker green on hover */ +} + +.draggable-field { + cursor: move; + padding: 5px; + background-color: #f9f9f9; + border: 1px solid #ddd; + border-radius: 4px; + text-align: center; + user-select: none; +} + +.draggable-field.dragging { + opacity: 0.5; +} + +.label-preview-container { + display: flex; + justify-content: center; /* Center horizontally */ + align-items: center; /* Center vertically */ + height: 100%; /* Full height of the parent container */ + position: relative; /* Ensure proper positioning */ +} + +#label-preview { + border: 1px solid #ddd; + padding: 10px; + min-height: 400px; + position: relative; + background-color: #f8f9fa; /* Light gray background */ + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for better visibility */ } \ No newline at end of file diff --git a/py_app/app/templates/create_template.html b/py_app/app/templates/create_template.html index c450b94..0802da5 100644 --- a/py_app/app/templates/create_template.html +++ b/py_app/app/templates/create_template.html @@ -22,11 +22,20 @@ +
+ +
+

Add Fields

+ + + + +

Get Database Headers

@@ -42,10 +51,7 @@
- -
- -
+
@@ -53,11 +59,20 @@

Interactive Label Preview

-

Preview the label with selected headers:

-
- +

Drag and drop fields to design your label:

+
+
+ +
+
+ + + {% endblock %} \ No newline at end of file