From 74717ef48c9eff6fde1ac202e067787507cdac1e Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Fri, 30 Jan 2026 22:35:18 +0000 Subject: [PATCH] Make photo uploader a custom component --- html/static/js/photo-upload.js | 164 +++++++++++++++++++++++++++++++++ rmo/template/nuisance.html | 27 +----- 2 files changed, 166 insertions(+), 25 deletions(-) create mode 100644 html/static/js/photo-upload.js diff --git a/html/static/js/photo-upload.js b/html/static/js/photo-upload.js new file mode 100644 index 00000000..3759e286 --- /dev/null +++ b/html/static/js/photo-upload.js @@ -0,0 +1,164 @@ +class PhotoUpload extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.render(); + } + + connectedCallback() { + setTimeout(() => this._initializeUploader(), 0); + } + + _initializeUploader() { + // Elements + const photoInput = this.shadowRoot.querySelector('#photos'); + + // Handle photo selection + photoInput.addEventListener('change', this._handlePhotoSelection); + + // Handle drag and drop + const photoDropArea = this.shadowRoot.querySelector('#photoDropArea'); + + photoDropArea.addEventListener('dragover', function(e) { + e.preventDefault(); + photoDropArea.style.backgroundColor = '#e9ecef'; + }); + + photoDropArea.addEventListener('dragleave', function() { + photoDropArea.style.backgroundColor = '#f8f9fa'; + }); + + photoDropArea.addEventListener('drop', function(e) { + e.preventDefault(); + photoDropArea.style.backgroundColor = '#f8f9fa'; + + if (e.dataTransfer.files.length) { + handleFiles(e.dataTransfer.files); + } + }); + } + render() { + const style = ` + + + `; + + // Create the table + let html = ` +
+ + + + +
+ + +
+ Take pictures of the mosquito problem area + + +
+ +
+
+ `; + + // Set the shadow DOM content + this.shadowRoot.innerHTML = style + html; + } + /** + * Handle photo selection and preview + */ + _handlePhotoSelection() { + const photoInput = document.getElementById('photos'); + const photoPreviewContainer = document.getElementById('photoPreviewContainer'); + + // Clear previous previews + photoPreviewContainer.innerHTML = ''; + + // Check if files were selected + if (photoInput.files && photoInput.files.length > 0) { + // Loop through selected files + Array.from(photoInput.files).forEach((file, index) => { + console.log("Handling", index, file); + if (!file.type.match('image.*')) { + console.log("Skipping non-image file", file.type); + return; // Skip non-image files + } + + // Create preview container + const previewContainer = document.createElement('div'); + previewContainer.className = 'position-relative m-1'; + + // Create image preview + const img = document.createElement('img'); + img.className = 'img-thumbnail'; + img.style.width = '100px'; + img.style.height = '100px'; + img.style.objectFit = 'cover'; + + // Read file and set preview + const reader = new FileReader(); + reader.onload = (e) => { + img.src = e.target.result; + }; + reader.readAsDataURL(file); + + // Create remove button + const removeBtn = document.createElement('button'); + removeBtn.type = 'button'; + removeBtn.className = 'btn btn-sm btn-danger position-absolute top-0 end-0'; + removeBtn.innerHTML = '×'; + removeBtn.style.fontSize = '10px'; + removeBtn.style.padding = '0 5px'; + + // Handle remove button click + removeBtn.addEventListener('click', function() { + // Create a new FileList without this file + // Since FileList is immutable, we need to reset the input + // This is a bit tricky and requires recreating the input + previewContainer.remove(); + + // If this was the last image, clear the input entirely + if (photoPreviewContainer.children.length === 0) { + photoInput.value = ''; + } + // Note: Unfortunately, selectively removing files from a FileList isn't straightforward + // In a real implementation, we might track selected files in an array and recreate the input + }); + + // Add elements to the preview container + previewContainer.appendChild(img); + previewContainer.appendChild(removeBtn); + photoPreviewContainer.appendChild(previewContainer); + }); + } + } + +} + +// Register the custom element +customElements.define('photo-upload', PhotoUpload); diff --git a/rmo/template/nuisance.html b/rmo/template/nuisance.html index a1f82ada..44c50e66 100644 --- a/rmo/template/nuisance.html +++ b/rmo/template/nuisance.html @@ -8,6 +8,7 @@ +