474 lines
14 KiB
JavaScript
474 lines
14 KiB
JavaScript
/**
|
|
* Gallery Layout Components
|
|
* Pure UI layout creation functions for the image gallery tab
|
|
* Extracted from imageGalleryTab.js for better organization and maintainability
|
|
*/
|
|
|
|
// Import required dependencies
|
|
import { createHeader } from "./cacheUIComponents.js";
|
|
import { createThumbnailGrid } from "./galleryComponents.js";
|
|
|
|
/**
|
|
* Creates the Gallery tab header section with status display
|
|
* @returns {HTMLElement} Header element with status display
|
|
*/
|
|
export function createGalleryHeader() {
|
|
const header = createHeader('Gallery', null); // No description for compactness
|
|
|
|
// Add status display area
|
|
const statusDiv = document.createElement('div');
|
|
statusDiv.style.cssText = `
|
|
font-size: 11px;
|
|
margin-top: 5px;
|
|
min-height: 16px;
|
|
color: #4CAF50;
|
|
font-style: italic;
|
|
`;
|
|
statusDiv.textContent = '';
|
|
|
|
header.appendChild(statusDiv);
|
|
header.statusDiv = statusDiv; // Store reference for easy access
|
|
|
|
return header;
|
|
}
|
|
|
|
/**
|
|
* Creates the combined folder selector and controls section for the Gallery tab
|
|
* @returns {Object} Folder selector and controls components
|
|
*/
|
|
export function createFolderSelectorAndControls() {
|
|
const folderSection = document.createElement('div');
|
|
folderSection.style.cssText = `
|
|
margin-bottom: 15px;
|
|
padding: 15px;
|
|
background: #2a2a2a;
|
|
border-radius: 6px;
|
|
border: 1px solid #444;
|
|
`;
|
|
|
|
const folderHeader = document.createElement('h4');
|
|
folderHeader.style.cssText = `
|
|
margin: 0 0 10px 0;
|
|
color: #4CAF50;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
`;
|
|
folderHeader.textContent = 'Folder & Controls';
|
|
|
|
const folderDropdown = document.createElement('select');
|
|
folderDropdown.id = 'gallery-folder-selector';
|
|
folderDropdown.style.cssText = `
|
|
width: 100%;
|
|
padding: 8px;
|
|
background: #333;
|
|
color: #fff;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
`;
|
|
|
|
// Default folder options
|
|
const defaultOptions = [
|
|
{ value: 'notes', text: '📝 Notes Folder', icon: '📝' },
|
|
{ value: 'input', text: '📥 Input Folder', icon: '📥' },
|
|
{ value: 'output', text: '📤 Output Folder', icon: '📤' },
|
|
{ value: 'custom', text: '📁 Browse Custom Folder...', icon: '📁' }
|
|
];
|
|
|
|
defaultOptions.forEach(option => {
|
|
const optionElement = document.createElement('option');
|
|
optionElement.value = option.value;
|
|
optionElement.textContent = option.text;
|
|
folderDropdown.appendChild(optionElement);
|
|
});
|
|
|
|
// Set default selection to notes
|
|
folderDropdown.value = 'notes';
|
|
|
|
const browseButton = document.createElement('button');
|
|
browseButton.textContent = 'Browse...';
|
|
browseButton.style.cssText = `
|
|
background: #2196F3;
|
|
color: white;
|
|
border: none;
|
|
padding: 6px 12px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
margin-top: 8px;
|
|
display: none;
|
|
`;
|
|
|
|
folderSection.appendChild(folderHeader);
|
|
folderSection.appendChild(folderDropdown);
|
|
folderSection.appendChild(browseButton);
|
|
|
|
// Add controls to the same section
|
|
// Sort controls
|
|
const sortContainer = document.createElement('div');
|
|
sortContainer.style.cssText = `
|
|
margin-top: 15px;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
gap: 8px;
|
|
align-items: center;
|
|
`;
|
|
|
|
const sortLabel = document.createElement('label');
|
|
sortLabel.textContent = 'Sort:';
|
|
sortLabel.style.cssText = `
|
|
color: #ccc;
|
|
font-size: 12px;
|
|
min-width: 35px;
|
|
`;
|
|
|
|
const sortSelect = document.createElement('select');
|
|
sortSelect.id = 'gallery-sort';
|
|
sortSelect.style.cssText = `
|
|
flex: 1;
|
|
padding: 4px 8px;
|
|
background: #333;
|
|
color: #fff;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
`;
|
|
|
|
const sortOptions = [
|
|
{ value: 'name', text: 'Name' },
|
|
{ value: 'date', text: 'Date Modified' },
|
|
{ value: 'size', text: 'File Size' },
|
|
{ value: 'type', text: 'File Type' }
|
|
];
|
|
|
|
sortOptions.forEach(option => {
|
|
const optionElement = document.createElement('option');
|
|
optionElement.value = option.value;
|
|
optionElement.textContent = option.text;
|
|
sortSelect.appendChild(optionElement);
|
|
});
|
|
|
|
const orderButton = document.createElement('button');
|
|
orderButton.textContent = '↑';
|
|
orderButton.title = 'Toggle sort order';
|
|
orderButton.style.cssText = `
|
|
background: #444;
|
|
color: white;
|
|
border: none;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
min-width: 30px;
|
|
`;
|
|
|
|
sortContainer.appendChild(sortLabel);
|
|
sortContainer.appendChild(sortSelect);
|
|
sortContainer.appendChild(orderButton);
|
|
|
|
// Thumbnail size and control buttons
|
|
const buttonsContainer = document.createElement('div');
|
|
buttonsContainer.style.cssText = `
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
`;
|
|
|
|
const thumbnailSizeSelect = document.createElement('select');
|
|
thumbnailSizeSelect.id = 'gallery-thumbnail-size';
|
|
thumbnailSizeSelect.style.cssText = `
|
|
flex: 1;
|
|
min-width: 80px;
|
|
padding: 4px 8px;
|
|
background: #333;
|
|
color: #fff;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
`;
|
|
|
|
const sizeOptions = [
|
|
{ value: 'small', text: 'Small' },
|
|
{ value: 'medium', text: 'Medium' },
|
|
{ value: 'large', text: 'Large' }
|
|
];
|
|
|
|
sizeOptions.forEach(option => {
|
|
const optionElement = document.createElement('option');
|
|
optionElement.value = option.value;
|
|
optionElement.textContent = option.text;
|
|
thumbnailSizeSelect.appendChild(optionElement);
|
|
});
|
|
|
|
const refreshButton = document.createElement('button');
|
|
refreshButton.textContent = '🔄';
|
|
refreshButton.title = 'Refresh images';
|
|
refreshButton.style.cssText = `
|
|
background: #4CAF50;
|
|
color: white;
|
|
border: none;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
`;
|
|
|
|
const viewModeButton = document.createElement('button');
|
|
viewModeButton.textContent = '⊞ Grid View';
|
|
viewModeButton.title = 'Toggle view mode';
|
|
viewModeButton.style.cssText = `
|
|
background: #2196F3;
|
|
color: white;
|
|
border: none;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
`;
|
|
|
|
buttonsContainer.appendChild(thumbnailSizeSelect);
|
|
buttonsContainer.appendChild(refreshButton);
|
|
buttonsContainer.appendChild(viewModeButton);
|
|
|
|
// Search bar - moved to bottom to match Models tab
|
|
const searchContainer = document.createElement('div');
|
|
searchContainer.style.cssText = `
|
|
margin-top: 15px;
|
|
display: flex;
|
|
gap: 8px;
|
|
align-items: center;
|
|
`;
|
|
|
|
// Add search label for better UX (matching Models tab)
|
|
const searchLabel = document.createElement('label');
|
|
searchLabel.textContent = 'Search:';
|
|
searchLabel.style.cssText = `
|
|
color: #ccc;
|
|
font-size: 12px;
|
|
min-width: 50px;
|
|
white-space: nowrap;
|
|
`;
|
|
|
|
const searchInput = document.createElement('input');
|
|
searchInput.type = 'text';
|
|
searchInput.id = 'gallery-search';
|
|
searchInput.placeholder = 'Search images...';
|
|
searchInput.style.cssText = `
|
|
flex: 1;
|
|
padding: 6px 10px;
|
|
background: #333;
|
|
color: #fff;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
`;
|
|
|
|
const clearButton = document.createElement('button');
|
|
clearButton.textContent = '✕';
|
|
clearButton.title = 'Clear search';
|
|
clearButton.style.cssText = `
|
|
background: #666;
|
|
color: white;
|
|
border: none;
|
|
padding: 6px 10px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
`;
|
|
|
|
searchContainer.appendChild(searchLabel);
|
|
searchContainer.appendChild(searchInput);
|
|
searchContainer.appendChild(clearButton);
|
|
|
|
folderSection.appendChild(sortContainer);
|
|
folderSection.appendChild(buttonsContainer);
|
|
folderSection.appendChild(searchContainer);
|
|
|
|
return {
|
|
folderSection,
|
|
folderHeader,
|
|
folderDropdown,
|
|
browseButton,
|
|
// Controls components
|
|
searchContainer,
|
|
searchInput,
|
|
clearButton,
|
|
sortContainer,
|
|
sortSelect,
|
|
orderButton,
|
|
buttonsContainer,
|
|
thumbnailSizeSelect,
|
|
refreshButton,
|
|
viewModeButton
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a wrapped thumbnail grid with header for the Gallery tab
|
|
* @returns {Object} Thumbnail grid components
|
|
*/
|
|
export function createWrappedThumbnailGrid() {
|
|
const gridSection = document.createElement('div');
|
|
gridSection.style.cssText = `
|
|
margin-bottom: 15px;
|
|
padding: 15px;
|
|
background: #2a2a2a;
|
|
border-radius: 6px;
|
|
border: 1px solid #444;
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
`;
|
|
|
|
const gridHeader = document.createElement('h4');
|
|
gridHeader.style.cssText = `
|
|
margin: 0 0 10px 0;
|
|
color: #4CAF50;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
`;
|
|
gridHeader.innerHTML = `
|
|
<span>Images <span id="image-count" style="color: #999; font-weight: normal;"></span></span>
|
|
`;
|
|
|
|
// Use imported thumbnail grid component
|
|
const grid = createThumbnailGrid();
|
|
grid.gridContainer.style.cssText += `
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
background: #333;
|
|
flex: 1;
|
|
`;
|
|
|
|
// Add placeholder content initially
|
|
grid.gridContainer.innerHTML = `
|
|
<div style="
|
|
grid-column: 1 / -1;
|
|
text-align: center;
|
|
color: #888;
|
|
padding: 40px;
|
|
font-style: italic;
|
|
">
|
|
🖼️ Select a folder to view images
|
|
</div>
|
|
`;
|
|
|
|
gridSection.appendChild(gridHeader);
|
|
gridSection.appendChild(grid.gridContainer);
|
|
|
|
// Replace the imageCountSpan with the one from header
|
|
const imageCountSpan = gridHeader.querySelector('#image-count');
|
|
|
|
return {
|
|
gridSection,
|
|
gridHeader,
|
|
gridContainer: grid.gridContainer,
|
|
imageCountSpan,
|
|
updateGridLayout: grid.updateGridLayout,
|
|
clear: grid.clear
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates the metadata panel section for the Gallery tab
|
|
* @returns {Object} Metadata panel components
|
|
*/
|
|
export function createMetadataPanel() {
|
|
const metadataSection = document.createElement('div');
|
|
metadataSection.style.cssText = `
|
|
padding: 15px;
|
|
background: #2a2a2a;
|
|
border-radius: 6px;
|
|
border: 1px solid #444;
|
|
display: block;
|
|
`;
|
|
|
|
const metadataHeader = document.createElement('h4');
|
|
metadataHeader.style.cssText = `
|
|
margin: 0 0 10px 0;
|
|
color: #4CAF50;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
`;
|
|
metadataHeader.innerHTML = `
|
|
<span>Image Details</span>
|
|
<button id="close-metadata" style="
|
|
background: #f44336;
|
|
color: white;
|
|
border: none;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 11px;
|
|
">Clear</button>
|
|
`;
|
|
|
|
const metadataContent = document.createElement('div');
|
|
metadataContent.id = 'metadata-content';
|
|
metadataContent.style.cssText = `
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
background: #333;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
padding: 15px;
|
|
color: #e0e0e0;
|
|
font-family: 'Courier New', monospace;
|
|
font-size: 11px;
|
|
line-height: 1.4;
|
|
`;
|
|
metadataContent.innerHTML = '<em style="color: #999;">Select an image to view details...</em>';
|
|
|
|
metadataSection.appendChild(metadataHeader);
|
|
metadataSection.appendChild(metadataContent);
|
|
|
|
return {
|
|
metadataSection,
|
|
metadataHeader,
|
|
metadataContent,
|
|
closeButton: metadataHeader.querySelector('#close-metadata')
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Assembles the complete gallery tab layout from individual components
|
|
* @param {HTMLElement} container - Container element to populate
|
|
* @param {Object} components - Layout components to assemble
|
|
*/
|
|
export function assembleGalleryTabLayout(container, components) {
|
|
const {
|
|
header,
|
|
folderAndControls, // Combined section
|
|
grid,
|
|
metadata
|
|
} = components;
|
|
|
|
// Clear container
|
|
container.innerHTML = '';
|
|
|
|
// Create main gallery container
|
|
const galleryContainer = document.createElement('div');
|
|
galleryContainer.style.cssText = `
|
|
padding: 15px;
|
|
`;
|
|
|
|
// Add header with reduced padding
|
|
header.style.padding = '10px 15px'; // Make header more compact
|
|
container.appendChild(header);
|
|
|
|
// Add all sections to gallery container
|
|
galleryContainer.appendChild(folderAndControls.folderSection); // Combined folder and controls
|
|
galleryContainer.appendChild(grid.gridSection);
|
|
galleryContainer.appendChild(metadata.metadataSection);
|
|
|
|
// Add gallery container to main container
|
|
container.appendChild(galleryContainer);
|
|
}
|