<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Interface - Tanishq Dubey Photography</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&display=swap" rel="stylesheet"> <style> body { margin: 0; padding: 0; font-family: 'Noto Sans Mono', monospace; background-color: #f0f0f0; } .container { max-width: 1200px; margin: 0 auto; padding: 2rem; } h1 { color: {{ accent_color }}; margin-bottom: 1.5rem; } .upload-form { background-color: #ffffff; padding: 1rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); margin-bottom: 2rem; } input[type="file"] { margin-right: 1rem; } input[type="submit"] { background-color: {{ accent_color }}; color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; font-family: inherit; font-weight: bold; } input[type="submit"]:hover { background-color: {{ accent_color }}e0; /* Slightly darker version of the accent color */ } table { width: 100%; border-collapse: collapse; background-color: #ffffff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } th, td { padding: 0.75rem; text-align: left; border-bottom: 1px solid #e0e0e0; } th { background-color: #f5f5f5; font-weight: bold; color: #333; } tr:hover { background-color: #f9f9f9; } .thumbnail { max-width: 100px; max-height: 100px; object-fit: cover; } .flash-messages { margin-bottom: 1rem; } .flash-messages p { background-color: #4CAF50; color: white; padding: 0.5rem; border-radius: 4px; } .logout { text-align: right; margin-bottom: 1rem; } .logout a { color: {{ accent_color }}; text-decoration: none; } .logout a:hover { text-decoration: underline; } .editable { cursor: pointer; } .editable:hover { background-color: #f0f0f0; } .editing { background-color: #fff; border: 1px solid #ccc; padding: 2px; } .delete-btn { background-color: #ff4136; color: white; border: none; padding: 0.25rem 0.5rem; border-radius: 4px; cursor: pointer; font-family: inherit; font-weight: bold; margin-left: 0.5rem; } .delete-btn:hover { background-color: #ff1a1a; } </style> </head> <body> <div class="container"> <div class="logout"> <a href="{{ url_for('admin_logout') }}">Logout</a> </div> <h1>Admin Interface</h1> {% with messages = get_flashed_messages() %} {% if messages %} <div class="flash-messages"> {% for message in messages %} <p>{{ message }}</p> {% endfor %} </div> {% endif %} {% endwith %} <div class="upload-form"> <h2>Upload New Image</h2> <form action="{{ url_for('admin_upload') }}" method="POST" enctype="multipart/form-data"> <input type="file" name="file" accept=".jpg,.jpeg,.png,.gif" required> <input type="submit" value="Upload"> </form> </div> <h2>Uploaded Images</h2> <table> <thead> <tr> <th>Thumbnail</th> <th>Filename</th> <th>Date Taken</th> <th>Focal Length</th> <th>Aperture</th> <th>Shutter Speed</th> <th>ISO</th> <th>Dimensions</th> <th>Actions</th> </tr> </thead> <tbody> {% for photo in photos %} <tr data-id="{{ photo.id }}"> <td><img src="{{ url_for('serve_thumbnail', filename=photo.thumbnail_filename) }}" alt="Thumbnail" class="thumbnail"></td> <td class="editable" data-field="input_filename">{{ photo.input_filename }}</td> <td class="editable" data-field="date_taken">{{ photo.date_taken.strftime('%Y-%m-%d %H:%M:%S') }}</td> <td class="editable" data-field="focal_length">{{ photo.focal_length }}</td> <td class="editable" data-field="aperture">{{ photo.aperture }}</td> <td class="editable" data-field="shutter_speed">{{ photo.shutter_speed }}</td> <td class="editable" data-field="iso">{{ photo.iso }}</td> <td>{{ photo.width }}x{{ photo.height }}</td> <td> <button onclick="saveChanges(this)">Save</button> <button onclick="deletePhoto(this)" class="delete-btn">Delete</button> </td> </tr> {% endfor %} </tbody> </table> </div> <script> function makeEditable(element) { const value = element.textContent; const input = document.createElement('input'); input.value = value; input.classList.add('editing'); element.textContent = ''; element.appendChild(input); input.focus(); input.addEventListener('blur', function() { element.textContent = this.value; element.classList.remove('editing'); }); } document.querySelectorAll('.editable').forEach(el => { el.addEventListener('click', function() { if (!this.classList.contains('editing')) { makeEditable(this); } }); }); function saveChanges(button) { const row = button.closest('tr'); const photoId = row.dataset.id; const updatedData = {}; row.querySelectorAll('.editable').forEach(el => { updatedData[el.dataset.field] = el.textContent; }); fetch('/admin/update_photo/' + photoId, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(updatedData), }) .then(response => response.json()) .then(data => { if (data.success) { alert('Changes saved successfully!'); } else { alert('Error saving changes: ' + data.error); } }) .catch((error) => { console.error('Error:', error); alert('An error occurred while saving changes.'); }); } function deletePhoto(button) { if (confirm('Are you sure you want to delete this photo?')) { const row = button.closest('tr'); const photoId = row.dataset.id; fetch('/admin/delete_photo/' + photoId, { method: 'POST', }) .then(response => response.json()) .then(data => { if (data.success) { row.remove(); alert('Photo deleted successfully!'); } else { alert('Error deleting photo: ' + data.error); } }) .catch((error) => { console.error('Error:', error); alert('An error occurred while deleting the photo.'); }); } } </script> </body> </html>