Cleanup of peeron download

This commit is contained in:
2025-09-25 21:42:15 +02:00
parent 74fe14f09b
commit 0a29543939
4 changed files with 179 additions and 221 deletions
+170
View File
@@ -0,0 +1,170 @@
// Peeron Socket class
class BrickPeeronSocket extends BrickSocket {
constructor(id, path, namespace, messages) {
super(id, path, namespace, messages, true);
// Form elements (built based on the initial id)
this.html_button = document.getElementById(id);
this.html_files = document.getElementById(`${id}-files`);
if (this.html_button) {
this.html_button.addEventListener("click", (e) => {
this.execute();
});
}
// Setup select all button
this.setup_select_all_button();
// Setup rotation buttons
this.setup_rotation_buttons();
// Setup the socket
this.setup();
}
setup_select_all_button() {
const selectAllButton = document.getElementById('peeron-select-all');
if (selectAllButton) {
selectAllButton.addEventListener('click', () => {
const checkboxes = this.get_files();
const allChecked = checkboxes.every(cb => cb.checked);
checkboxes.forEach(cb => cb.checked = !allChecked);
// Update button text and icon
if (allChecked) {
selectAllButton.innerHTML = '<i class="ri-checkbox-multiple-line"></i> Select All';
} else {
selectAllButton.innerHTML = '<i class="ri-checkbox-blank-line"></i> Deselect All';
}
});
}
}
setup_rotation_buttons() {
document.querySelectorAll('.peeron-rotate-btn').forEach(button => {
button.addEventListener('click', (e) => {
e.preventDefault(); // Prevent label click
e.stopPropagation(); // Stop event bubbling
const targetId = button.getAttribute('data-target');
const checkboxId = button.getAttribute('data-checkbox');
const targetImg = document.getElementById(targetId);
const checkbox = document.getElementById(checkboxId);
if (targetImg && checkbox) {
let currentRotation = parseInt(button.getAttribute('data-rotation') || '0');
currentRotation = (currentRotation + 90) % 360;
// Update image rotation
targetImg.style.transform = `rotate(${currentRotation}deg)`;
button.setAttribute('data-rotation', currentRotation.toString());
// Store rotation in checkbox data for later use
checkbox.setAttribute('data-rotation', currentRotation.toString());
// Update the rotation icon to indicate current state
const icon = button.querySelector('i');
if (icon) {
// Rotate the icon to match the image rotation
icon.style.transform = `rotate(${currentRotation}deg)`;
}
}
});
});
}
// Upon receiving a complete message
complete(data) {
super.complete(data);
// Clear progress display after completion
if (this.html_progress_message) {
this.html_progress_message.classList.add("d-none");
this.html_progress_message.textContent = "";
}
if (this.html_count) {
this.html_count.classList.add("d-none");
this.html_count.textContent = "";
}
// Ensure spinner is hidden
this.spinner(false);
this.toggle(true);
}
// Execute the action
execute() {
if (!this.disabled && this.socket !== undefined && this.socket.connected) {
this.toggle(false);
this.download_peeron_pages();
}
}
// Get the list of checkboxes describing files
get_files(checked=false) {
let files = [];
if (this.html_files) {
files = [...this.html_files.querySelectorAll('input[type="checkbox"]')];
if (checked) {
files = files.filter(file => file.checked);
}
}
return files;
}
// Download Peeron pages
download_peeron_pages() {
if (this.html_files) {
const selectedFiles = this.get_files(true);
if (selectedFiles.length === 0) {
this.fail({message: "Please select at least one page to download."});
this.toggle(true);
return;
}
const pages = selectedFiles.map(checkbox => ({
page_number: checkbox.getAttribute('data-page-number'),
thumbnail_url: checkbox.getAttribute('data-thumbnail-url'),
image_url: checkbox.getAttribute('data-image-url'),
alt_text: checkbox.getAttribute('data-alt-text'),
rotation: parseInt(checkbox.getAttribute('data-rotation') || '0')
}));
this.clear();
this.spinner(true);
const setElement = document.querySelector('input[name="download-set"]');
const set = setElement ? setElement.value : '';
this.socket.emit(this.messages.DOWNLOAD_PEERON_PAGES, {
set: set,
pages: pages,
total: pages.length,
current: 0
});
} else {
this.fail({message: "Could not find the list of pages to download"});
}
}
// Toggle clicking on the button, or sending events
toggle(enabled) {
super.toggle(enabled);
if (this.html_files) {
this.get_files().forEach(el => el.disabled = !enabled);
}
if (this.html_button) {
this.html_button.disabled = !enabled;
}
}
}
+6
View File
@@ -104,6 +104,12 @@
{% endif %}
{% if request.endpoint == 'set.list' %}
<script src="{{ url_for('static', filename='scripts/sets.js') }}"></script>
{% endif %}
{% if request.endpoint == 'set.details' %}
<script src="{{ url_for('static', filename='scripts/parts-bulk-operations.js') }}"></script>
{% endif %}
{% if request.endpoint == 'instructions.download' or request.endpoint == 'instructions.do_download' %}
<script src="{{ url_for('static', filename='scripts/socket/peeron.js') }}"></script>
{% endif %}
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", () => {
+2 -176
View File
@@ -1,184 +1,10 @@
<script type="text/javascript">
// Wait for all scripts to load, then initialize Peeron socket
window.addEventListener('load', () => {
// Double-check that BrickSocket is available
if (typeof BrickSocket === 'undefined') {
console.error('BrickSocket is not available after page load');
return;
}
// Define Peeron socket class after BrickSocket is guaranteed to be available
class BrickPeeronSocket extends BrickSocket {
constructor(id, path, namespace, messages) {
super(id, path, namespace, messages, true);
// Form elements
this.html_button = document.getElementById(id);
this.html_files = document.getElementById(`${id}-files`);
if (this.html_button) {
this.html_button.addEventListener("click", (e) => {
this.execute();
});
}
// Setup select all button (now in template)
this.setup_select_all_button();
// Setup rotation buttons
this.setup_rotation_buttons();
// Setup the socket
this.setup();
}
setup_select_all_button() {
const selectAllButton = document.getElementById('peeron-select-all');
if (selectAllButton) {
selectAllButton.addEventListener('click', () => {
const checkboxes = this.get_files();
const allChecked = checkboxes.every(cb => cb.checked);
checkboxes.forEach(cb => cb.checked = !allChecked);
// Update button text and icon
if (allChecked) {
selectAllButton.innerHTML = '<i class="ri-checkbox-multiple-line"></i> Select All';
} else {
selectAllButton.innerHTML = '<i class="ri-checkbox-blank-line"></i> Deselect All';
}
});
}
}
setup_rotation_buttons() {
document.querySelectorAll('.peeron-rotate-btn').forEach(button => {
button.addEventListener('click', (e) => {
e.preventDefault(); // Prevent label click
e.stopPropagation(); // Stop event bubbling
const targetId = button.getAttribute('data-target');
const checkboxId = button.getAttribute('data-checkbox');
const targetImg = document.getElementById(targetId);
const checkbox = document.getElementById(checkboxId);
if (targetImg && checkbox) {
let currentRotation = parseInt(button.getAttribute('data-rotation') || '0');
currentRotation = (currentRotation + 90) % 360;
// Update image rotation
targetImg.style.transform = `rotate(${currentRotation}deg)`;
button.setAttribute('data-rotation', currentRotation.toString());
// Store rotation in checkbox data for later use
checkbox.setAttribute('data-rotation', currentRotation.toString());
// Update the rotation icon to indicate current state
const icon = button.querySelector('i');
if (icon) {
// Rotate the icon to match the image rotation
icon.style.transform = `rotate(${currentRotation}deg)`;
}
}
});
});
}
complete(data) {
super.complete(data);
// Clear progress display after completion
if (this.html_progress_message) {
this.html_progress_message.classList.add("d-none");
this.html_progress_message.textContent = "";
}
if (this.html_count) {
this.html_count.classList.add("d-none");
this.html_count.textContent = "";
}
// Ensure spinner is hidden
this.spinner(false);
this.toggle(true);
}
execute() {
if (!this.disabled && this.socket !== undefined && this.socket.connected) {
this.toggle(false);
this.download_peeron_pages();
}
}
get_files(checked=false) {
let files = [];
if (this.html_files) {
files = [...this.html_files.querySelectorAll('input[type="checkbox"]')];
if (checked) {
files = files.filter(file => file.checked);
}
}
return files;
}
download_peeron_pages() {
if (this.html_files) {
const selectedFiles = this.get_files(true);
if (selectedFiles.length === 0) {
this.fail({message: "Please select at least one page to download."});
this.toggle(true);
return;
}
const pages = selectedFiles.map(checkbox => ({
page_number: checkbox.getAttribute('data-page-number'),
thumbnail_url: checkbox.getAttribute('data-thumbnail-url'),
image_url: checkbox.getAttribute('data-image-url'),
alt_text: checkbox.getAttribute('data-alt-text'),
rotation: parseInt(checkbox.getAttribute('data-rotation') || '0')
}));
this.clear();
this.spinner(true);
const setElement = document.querySelector('input[name="download-set"]');
const set = setElement ? setElement.value : '';
this.socket.emit(this.messages.DOWNLOAD_PEERON_PAGES, {
set: set,
pages: pages,
total: pages.length,
current: 0
});
} else {
this.fail({message: "Could not find the list of pages to download"});
}
}
toggle(enabled) {
super.toggle(enabled);
if (this.html_files) {
this.get_files().forEach(el => el.disabled = !enabled);
}
if (this.html_button) {
this.html_button.disabled = !enabled;
}
}
}
// Initialize the socket
try {
document.addEventListener("DOMContentLoaded", () => {
new BrickPeeronSocket('peeron-download', '{{ path }}', '{{ namespace }}', {
COMPLETE: '{{ messages['COMPLETE'] }}',
DOWNLOAD_PEERON_PAGES: 'download_peeron_pages',
FAIL: '{{ messages['FAIL'] }}',
PROGRESS: '{{ messages['PROGRESS'] }}',
});
} catch (error) {
console.error('Error initializing BrickPeeronSocket:', error);
}
});
});
</script>
+1 -45
View File
@@ -58,8 +58,7 @@
<div class="text-center position-relative">
<div class="position-relative d-inline-block">
<img id="peeron-img-{{ loop.index }}" src="{{ page.thumbnail_url }}" alt="{{ page.alt_text }}"
class="img-fluid mb-2 border rounded" style="max-height: 150px; transform: rotate(0deg); transition: transform 0.3s ease;"
data-dims-target="peeron-dims-{{ loop.index }}">
class="img-fluid mb-2 border rounded" style="max-height: 150px; transform: rotate(0deg); transition: transform 0.3s ease;">
<button type="button" class="btn btn-sm btn-light position-absolute top-0 end-0 p-1 me-1 mt-1 peeron-rotate-btn"
data-target="peeron-img-{{ loop.index }}" data-checkbox="peeron-page-{{ loop.index }}" data-rotation="0"
title="Rotate page" style="font-size: 0.7rem; line-height: 1;">
@@ -67,7 +66,6 @@
</button>
</div>
<div class="small fw-bold">Page {{ page.page_number }}</div>
<div id="peeron-dims-{{ loop.index }}" class="small text-muted">Loading dimensions...</div>
</div>
</label>
</div>
@@ -102,46 +100,4 @@
</div>
</div>
<script>
// Function to show image dimensions
function showImageDimensions(img, dimElementId) {
const dimElement = document.getElementById(dimElementId);
if (dimElement && img.naturalWidth && img.naturalHeight) {
dimElement.textContent = `${img.naturalWidth} × ${img.naturalHeight} px`;
dimElement.classList.remove('text-muted');
dimElement.classList.add('text-info');
} else if (dimElement) {
dimElement.textContent = 'Dimensions unavailable';
}
}
// Initialize dimensions for all images when page loads
document.addEventListener('DOMContentLoaded', function() {
// Wait for all images to load and then show dimensions
const images = document.querySelectorAll('img[data-dims-target]');
images.forEach(img => {
const targetId = img.getAttribute('data-dims-target');
// Check if already loaded
if (img.complete && img.naturalWidth && img.naturalHeight) {
showImageDimensions(img, targetId);
} else {
// Wait for load
img.addEventListener('load', function() {
showImageDimensions(this, targetId);
});
// Handle error case
img.addEventListener('error', function() {
const dimElement = document.getElementById(targetId);
if (dimElement) {
dimElement.textContent = 'Failed to load';
dimElement.classList.remove('text-muted');
dimElement.classList.add('text-danger');
}
});
}
});
});
</script>
{% endblock %}