198 lines
8.6 KiB
JavaScript
198 lines
8.6 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function() {
|
|
const selectionGrid = document.getElementById('selection-grid');
|
|
// Unified filter state
|
|
const filterState = {
|
|
action: 'all',
|
|
orientation: 'all',
|
|
resolution: 'all'
|
|
};
|
|
const resolutionFilter = document.getElementById('resolution-filter');
|
|
const selectAllBtn = document.getElementById('select-all');
|
|
const deselectAllBtn = document.getElementById('deselect-all');
|
|
const downloadSelectedBtn = document.getElementById('download-selected');
|
|
|
|
const actionModal = document.getElementById('action-modal');
|
|
const closeActionModal = document.getElementById('close-action-modal');
|
|
const actionButtons = actionModal.querySelectorAll('.action-btn');
|
|
const modalPreviewImg = document.getElementById('modal-preview-img');
|
|
const modalMessage = document.getElementById('modal-message');
|
|
|
|
const resetBtn = document.getElementById('reset-db');
|
|
const resetModal = document.getElementById('reset-modal');
|
|
const confirmResetBtn = document.getElementById('confirm-reset');
|
|
const cancelResetBtn = document.getElementById('cancel-reset');
|
|
const resetMessage = document.getElementById('reset-message');
|
|
|
|
let cachedSelections = [];
|
|
let selectedItems = [];
|
|
let currentSelectionId = null;
|
|
|
|
const loadSelections = () => {
|
|
selectionGrid.innerHTML = `<div class="no-selections">Loading selections...</div>`;
|
|
|
|
fetch('/selections')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.selections && data.selections.length > 0) {
|
|
cachedSelections = data.selections;
|
|
populateResolutionFilter(cachedSelections);
|
|
renderSelections();
|
|
} else {
|
|
selectionGrid.innerHTML = '<div class="no-selections">No selections found</div>';
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading selections:', error);
|
|
selectionGrid.innerHTML = `<div class="error">Error loading selections: ${error.message}</div>`;
|
|
});
|
|
};
|
|
|
|
const populateResolutionFilter = (selections) => {
|
|
const resolutions = [...new Set(selections.map(s => s.resolution))].sort();
|
|
resolutionFilter.innerHTML = '<option value="all">All Resolutions</option>';
|
|
resolutions.forEach(resolution => {
|
|
const option = document.createElement('option');
|
|
option.value = resolution;
|
|
option.textContent = resolution;
|
|
resolutionFilter.appendChild(option);
|
|
});
|
|
};
|
|
|
|
const renderSelections = () => {
|
|
selectionGrid.innerHTML = '';
|
|
const selections = cachedSelections;
|
|
|
|
const filteredSelections = selections.filter(s =>
|
|
(filterState.action === 'all' || s.action === filterState.action) &&
|
|
(filterState.orientation === 'all' || s.orientation === filterState.orientation) &&
|
|
(filterState.resolution === 'all' || s.resolution === filterState.resolution)
|
|
);
|
|
|
|
if (filteredSelections.length === 0) {
|
|
selectionGrid.innerHTML = '<div class="no-selections">No selections match the current filters</div>';
|
|
return;
|
|
}
|
|
|
|
filteredSelections.forEach(selection => {
|
|
const item = document.createElement('div');
|
|
item.className = 'selection-item';
|
|
item.dataset.id = selection.id;
|
|
item.innerHTML = `
|
|
<div class="selection-checkbox-container">
|
|
<input type="checkbox" class="selection-checkbox">
|
|
</div>
|
|
<img src="${selection.image_path}" alt="Selected image" loading="lazy">
|
|
<div class="selection-action action-${actionClass(selection.action)}">${selection.action}</div>
|
|
<div class="selection-info">
|
|
<p>${selection.image_path.split('/').pop()}</p>
|
|
<p>Resolution: ${selection.resolution}</p>
|
|
</div>
|
|
<div class="selection-controls">
|
|
<button class="control-btn edit-btn">Change</button>
|
|
<button class="control-btn delete-btn">Remove</button>
|
|
</div>
|
|
`;
|
|
selectionGrid.appendChild(item);
|
|
});
|
|
};
|
|
|
|
const actionClass = (action) => {
|
|
const map = { 'Discard':'discard', 'Keep':'keep', 'Favorite':'favorite', 'Review':'review' };
|
|
return map[action] || 'discard';
|
|
};
|
|
const getActionName = (action) => action;
|
|
|
|
const updateDownloadButton = () => {
|
|
downloadSelectedBtn.disabled = selectedItems.length === 0;
|
|
downloadSelectedBtn.querySelector('.label').textContent = selectedItems.length > 0 ? `Download (${selectedItems.length})` : 'Download';
|
|
};
|
|
|
|
selectionGrid.addEventListener('click', (e) => {
|
|
const target = e.target;
|
|
const selectionItem = target.closest('.selection-item');
|
|
if (!selectionItem) return;
|
|
|
|
const selectionId = selectionItem.dataset.id;
|
|
const selection = { id: selectionId, image_path: selectionItem.querySelector('img').src };
|
|
|
|
if (target.classList.contains('selection-checkbox')) {
|
|
if (target.checked) {
|
|
selectionItem.classList.add('selected');
|
|
selectedItems.push(selection);
|
|
} else {
|
|
selectionItem.classList.remove('selected');
|
|
selectedItems = selectedItems.filter(item => item.id !== selectionId);
|
|
}
|
|
updateDownloadButton();
|
|
} else if (target.classList.contains('edit-btn')) {
|
|
currentSelectionId = selectionId;
|
|
modalPreviewImg.src = selection.image_path;
|
|
actionModal.style.display = 'flex';
|
|
} else if (target.classList.contains('delete-btn')) {
|
|
if (confirm('Are you sure you want to delete this selection?')) {
|
|
// Implement delete functionality
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delegated click handler for any filter button
|
|
document.querySelector('.filter-container').addEventListener('click', (e) => {
|
|
const btn = e.target.closest('.filter-btn');
|
|
if (!btn) return;
|
|
|
|
// Determine filter type and value
|
|
const { filter, orientation } = btn.dataset;
|
|
if (filter !== undefined) {
|
|
filterState.action = filter;
|
|
// update active classes within the same group
|
|
btn.parentElement.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
}
|
|
if (orientation !== undefined) {
|
|
filterState.orientation = orientation;
|
|
btn.parentElement.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
}
|
|
btn.classList.add('active');
|
|
renderSelections();
|
|
});
|
|
|
|
resolutionFilter.addEventListener('change', function() {
|
|
filterState.resolution = this.value;
|
|
renderSelections();
|
|
});
|
|
|
|
selectAllBtn.addEventListener('click', () => {
|
|
document.querySelectorAll('.selection-checkbox').forEach(cb => cb.checked = true);
|
|
selectedItems = Array.from(document.querySelectorAll('.selection-item')).map(item => ({id: item.dataset.id, image_path: item.querySelector('img').src}));
|
|
document.querySelectorAll('.selection-item').forEach(item => item.classList.add('selected'));
|
|
updateDownloadButton();
|
|
});
|
|
|
|
deselectAllBtn.addEventListener('click', () => {
|
|
document.querySelectorAll('.selection-checkbox').forEach(cb => cb.checked = false);
|
|
selectedItems = [];
|
|
document.querySelectorAll('.selection-item').forEach(item => item.classList.remove('selected'));
|
|
updateDownloadButton();
|
|
});
|
|
|
|
downloadSelectedBtn.addEventListener('click', () => {
|
|
const paths = selectedItems.map(item => item.image_path);
|
|
const query = paths.map(p => `paths=${encodeURIComponent(p)}`).join('&');
|
|
window.location.href = `/download-selected?${query}`;
|
|
});
|
|
|
|
closeActionModal.addEventListener('click', () => actionModal.style.display = 'none');
|
|
|
|
actionButtons.forEach(button => button.addEventListener('click', function() {
|
|
const action = this.dataset.action;
|
|
// Implement update action functionality
|
|
}));
|
|
|
|
resetBtn.addEventListener('click', () => resetModal.style.display = 'flex');
|
|
confirmResetBtn.addEventListener('click', () => {
|
|
// Implement reset database functionality
|
|
});
|
|
cancelResetBtn.addEventListener('click', () => resetModal.style.display = 'none');
|
|
|
|
loadSelections();
|
|
});
|