updated template creation

This commit is contained in:
2025-05-07 16:38:40 +03:00
parent 31e0ffd6dc
commit 45c9669393
5 changed files with 362 additions and 142 deletions

View File

@@ -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,
};

29
py_app/app/static/pdfjs/pdf.worker.js vendored Normal file
View File

@@ -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 };

View File

@@ -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.');
}
});
// Handle fetching database tables
getTablesBtn.addEventListener('click', () => {
fetch('/get_tables')
.then(response => response.json())
.then(data => {
tablesContainer.innerHTML = '<h4>Select a Table:</h4>';
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));
});
// Fetch columns for a selected table
function fetchColumns(table) {
fetch(`/get_columns?table=${table}`)
.then(response => response.json())
.then(data => {
columnsContainer.innerHTML = '<h4>Select Columns:</h4>';
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'));
// Update label preview on checkbox change
checkbox.addEventListener('change', updateLabelPreview);
});
})
.catch(error => console.error('Error fetching columns:', error));
}
// Update the label preview
function updateLabelPreview() {
const selectedColumns = Array.from(columnsContainer.querySelectorAll('input[type="checkbox"]:checked'))
.map(checkbox => checkbox.value);
labelPreview.innerHTML = '<h4>Label Preview:</h4>';
selectedColumns.forEach(column => {
const div = document.createElement('div');
div.textContent = column;
labelPreview.appendChild(div);
});
}
// 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.');
if (!widthInput || !heightInput) {
alert('Please enter valid dimensions for width and height.');
return;
}
const width = document.getElementById('label-width').value;
const height = document.getElementById('label-height').value;
// Convert mm to pixels (1 mm = 3.779528 pixels)
const widthPixels = parseFloat(widthInput) * 3.779528;
const heightPixels = parseFloat(heightInput) * 3.779528;
if (!width || !height) {
alert('Please set the label dimensions.');
return;
// 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);
});
});
// 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';
switch (type) {
case 'text-label':
field.textContent = 'Text Label';
field.style.fontSize = '14px';
break;
case 'text-input':
field.innerHTML = '<input type="text" placeholder="Input Field" style="width: 100px;">';
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;
}
const templateData = {
width,
height,
columns: selectedColumns
};
labelPreview.appendChild(field);
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;
// Make the field draggable
makeFieldDraggable(field);
}
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));
// Function to make a field draggable
function makeFieldDraggable(field) {
field.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', null);
field.classList.add('dragging');
});
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`;
});
}
});

View File

@@ -691,3 +691,34 @@ 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 */
}

View File

@@ -22,11 +22,20 @@
<label for="label-height">Height (mm):</label>
<input type="number" id="label-height" name="label_height" required>
</div>
<button type="button" id="set-dimensions-btn" class="btn">Set Label Dimensions</button>
</form>
</div>
<hr style="margin: 20px 0;">
<!-- Add Fields Section -->
<div>
<h4>Add Fields</h4>
<button type="button" class="btn add-field-btn" data-type="text-label">Add Text Label</button>
<button type="button" class="btn add-field-btn" data-type="text-input">Add Text Input</button>
<button type="button" class="btn add-field-btn" data-type="barcode">Add Barcode</button>
<button type="button" class="btn add-field-btn" data-type="qrcode">Add QR Code</button>
</div>
<!-- Get Database Headers Section -->
<div>
<h4>Get Database Headers</h4>
@@ -42,10 +51,7 @@
<hr style="margin: 20px 0;">
<!-- Generate PDF Template -->
<div>
<button type="button" id="generate-pdf-btn" class="btn">Generate PDF Template</button>
</div>
</div>
</div>
@@ -53,11 +59,20 @@
<div class="right-column" style="flex: 2;">
<div class="dashboard-card">
<h3>Interactive Label Preview</h3>
<p>Preview the label with selected headers:</p>
<div id="label-preview" style="border: 1px solid #ddd; padding: 10px; min-height: 200px;">
<!-- Label preview will be dynamically updated here -->
</div>
<p>Drag and drop fields to design your label:</p>
<div class="label-preview-container" style="display: flex; justify-content: center; align-items: center; height: 100%; position: relative;">
<div id="label-preview" style="border: 1px solid #ddd; padding: 10px; min-height: 400px; position: relative;">
<!-- Fields will be dynamically added here -->
</div>
</div>
<button type="button" id="preview-btn" class="btn" style="margin-top: 10px;">Preview</button>
</div>
</div>
</div>
<script src="{{ url_for('static', filename='pdfjs/pdf.worker.js') }}"></script>
<script>
// Set the worker source for PDF.js
pdfjsLib.GlobalWorkerOptions.workerSrc = "{{ url_for('static', filename='pdfjs/pdf.worker.min.js') }}";
</script>
{% endblock %}