updated template creation
This commit is contained in:
203
py_app/app/static/pdfjs/pdf.js
Normal file
203
py_app/app/static/pdfjs/pdf.js
Normal 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
29
py_app/app/static/pdfjs/pdf.worker.js
vendored
Normal 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 };
|
||||
@@ -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`;
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
labelPreview.appendChild(field);
|
||||
|
||||
// Make the field draggable
|
||||
makeFieldDraggable(field);
|
||||
}
|
||||
|
||||
// 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`;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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 -->
|
||||
<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 %}
|
||||
Reference in New Issue
Block a user