mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Add filters - base model only for now
This commit is contained in:
@@ -121,6 +121,10 @@ class ApiRoutes:
|
||||
fuzzy = request.query.get('fuzzy', 'false').lower() == 'true'
|
||||
recursive = request.query.get('recursive', 'false').lower() == 'true'
|
||||
|
||||
# Parse base models filter parameter
|
||||
base_models = request.query.get('base_models', '').split(',')
|
||||
base_models = [model.strip() for model in base_models if model.strip()]
|
||||
|
||||
# Validate parameters
|
||||
if page < 1 or page_size < 1 or page_size > 100:
|
||||
return web.json_response({
|
||||
@@ -132,7 +136,7 @@ class ApiRoutes:
|
||||
'error': 'Invalid sort parameter'
|
||||
}, status=400)
|
||||
|
||||
# Get paginated data with search
|
||||
# Get paginated data with search and filters
|
||||
result = await self.scanner.get_paginated_data(
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
@@ -140,7 +144,8 @@ class ApiRoutes:
|
||||
folder=folder,
|
||||
search=search,
|
||||
fuzzy=fuzzy,
|
||||
recursive=recursive # 添加递归参数
|
||||
recursive=recursive,
|
||||
base_models=base_models # Pass base models filter
|
||||
)
|
||||
|
||||
# Format the response data
|
||||
|
||||
@@ -148,7 +148,7 @@ class LoraScanner:
|
||||
|
||||
async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'name',
|
||||
folder: str = None, search: str = None, fuzzy: bool = False,
|
||||
recursive: bool = False):
|
||||
recursive: bool = False, base_models: list = None):
|
||||
"""Get paginated and filtered lora data
|
||||
|
||||
Args:
|
||||
@@ -159,6 +159,7 @@ class LoraScanner:
|
||||
search: Search term
|
||||
fuzzy: Use fuzzy matching for search
|
||||
recursive: Include subfolders when folder filter is applied
|
||||
base_models: List of base models to filter by
|
||||
"""
|
||||
cache = await self.get_cached_data()
|
||||
|
||||
@@ -180,6 +181,13 @@ class LoraScanner:
|
||||
if item['folder'] == folder
|
||||
]
|
||||
|
||||
# Apply base model filtering
|
||||
if base_models and len(base_models) > 0:
|
||||
filtered_data = [
|
||||
item for item in filtered_data
|
||||
if item.get('base_model') in base_models
|
||||
]
|
||||
|
||||
# 应用搜索过滤
|
||||
if search:
|
||||
if fuzzy:
|
||||
|
||||
@@ -2,10 +2,10 @@ from typing import Optional
|
||||
|
||||
# Base model mapping based on version string
|
||||
BASE_MODEL_MAPPING = {
|
||||
"sd-v1-5": "SD1.5",
|
||||
"sd-v2-1": "SD2.1",
|
||||
"sdxl": "SDXL",
|
||||
"sd-v2": "SD2.0",
|
||||
"sd-v1-5": "SD 1.5",
|
||||
"sd-v2-1": "SD 2.1",
|
||||
"sdxl": "SDXL 1.0",
|
||||
"sd-v2": "SD 2.0",
|
||||
"flux1": "Flux.1 D",
|
||||
"flux.1 d": "Flux.1 D",
|
||||
"illustrious": "IL",
|
||||
|
||||
@@ -438,6 +438,10 @@
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
user-select: none; /* Prevent text selection */
|
||||
-webkit-user-select: none; /* For Safari */
|
||||
-moz-user-select: none; /* For Firefox */
|
||||
-ms-user-select: none; /* For IE/Edge */
|
||||
}
|
||||
|
||||
.filter-tag:hover {
|
||||
@@ -467,42 +471,28 @@
|
||||
/* Filter actions */
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
margin-top: 16px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.clear-filters-btn,
|
||||
.apply-filters-btn {
|
||||
padding: 6px 12px;
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.clear-filters-btn {
|
||||
background-color: transparent;
|
||||
color: var(--text-color);
|
||||
border: 1px solid var(--border-color);
|
||||
flex: 1;
|
||||
padding: 6px 12px;
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.clear-filters-btn:hover {
|
||||
background-color: var(--lora-surface-hover);
|
||||
}
|
||||
|
||||
.apply-filters-btn {
|
||||
background-color: var(--lora-accent);
|
||||
color: white;
|
||||
border: 1px solid var(--lora-accent);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.apply-filters-btn:hover {
|
||||
background-color: var(--lora-accent-hover, var(--lora-accent));
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
/* Remove apply-filters-btn styles since we no longer need it */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.actions {
|
||||
|
||||
@@ -30,6 +30,12 @@ export async function loadMoreLoras(boolUpdateFolders = false) {
|
||||
params.append('search', searchInput.value.trim());
|
||||
params.append('fuzzy', 'true');
|
||||
}
|
||||
|
||||
// Add filter parameters if active
|
||||
if (state.filters && state.filters.baseModel && state.filters.baseModel.length > 0) {
|
||||
// Convert the array of base models to a comma-separated string
|
||||
params.append('base_models', state.filters.baseModel.join(','));
|
||||
}
|
||||
|
||||
console.log('Loading loras with params:', params.toString());
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
modalManager.initialize(); // Initialize modalManager after DOM is loaded
|
||||
window.downloadManager = new DownloadManager(); // Move this after modalManager initialization
|
||||
window.filterManager = new FilterManager(); // Initialize filter manager
|
||||
|
||||
// Initialize state filters from filterManager if available
|
||||
if (window.filterManager && window.filterManager.filters) {
|
||||
state.filters = { ...window.filterManager.filters };
|
||||
}
|
||||
|
||||
initializeInfiniteScroll();
|
||||
initializeEventListeners();
|
||||
lazyLoadImages();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BASE_MODELS, BASE_MODEL_CLASSES } from '../utils/constants.js';
|
||||
import { state } from '../state/index.js';
|
||||
import { showToast } from '../utils/uiHelpers.js';
|
||||
import { resetAndReload } from '../api/loraApi.js';
|
||||
|
||||
export class FilterManager {
|
||||
constructor() {
|
||||
@@ -45,8 +46,8 @@ export class FilterManager {
|
||||
tag.dataset.baseModel = value;
|
||||
tag.innerHTML = value;
|
||||
|
||||
// Add click handler to toggle selection
|
||||
tag.addEventListener('click', () => {
|
||||
// Add click handler to toggle selection and automatically apply
|
||||
tag.addEventListener('click', async () => {
|
||||
tag.classList.toggle('active');
|
||||
|
||||
if (tag.classList.contains('active')) {
|
||||
@@ -58,6 +59,9 @@ export class FilterManager {
|
||||
}
|
||||
|
||||
this.updateActiveFiltersCount();
|
||||
|
||||
// Auto-apply filter when tag is clicked
|
||||
await this.applyFilters(false);
|
||||
});
|
||||
|
||||
baseModelTagsContainer.appendChild(tag);
|
||||
@@ -101,30 +105,39 @@ export class FilterManager {
|
||||
}
|
||||
}
|
||||
|
||||
applyFilters() {
|
||||
async applyFilters(showToastNotification = true) {
|
||||
// Save filters to localStorage
|
||||
localStorage.setItem('loraFilters', JSON.stringify(this.filters));
|
||||
|
||||
// Apply filters to cards (will be implemented later)
|
||||
showToast('Filters applied', 'success');
|
||||
// Update state with current filters
|
||||
state.filters = { ...this.filters };
|
||||
|
||||
// Close the filter panel
|
||||
this.closeFilterPanel();
|
||||
// Reload loras with filters applied
|
||||
await resetAndReload();
|
||||
|
||||
// Update filter button to show active state
|
||||
if (this.hasActiveFilters()) {
|
||||
this.filterButton.classList.add('active');
|
||||
if (showToastNotification) {
|
||||
showToast(`Filtering by ${this.filters.baseModel.length} base models`, 'success');
|
||||
}
|
||||
} else {
|
||||
this.filterButton.classList.remove('active');
|
||||
if (showToastNotification) {
|
||||
showToast('Filters cleared', 'info');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearFilters() {
|
||||
async clearFilters() {
|
||||
// Clear all filters
|
||||
this.filters = {
|
||||
baseModel: []
|
||||
};
|
||||
|
||||
// Update state
|
||||
state.filters = { ...this.filters };
|
||||
|
||||
// Update UI
|
||||
this.updateTagSelections();
|
||||
this.updateActiveFiltersCount();
|
||||
@@ -132,8 +145,9 @@ export class FilterManager {
|
||||
// Remove from localStorage
|
||||
localStorage.removeItem('loraFilters');
|
||||
|
||||
// Update UI and reload data
|
||||
this.filterButton.classList.remove('active');
|
||||
showToast('All filters cleared', 'info');
|
||||
await resetAndReload();
|
||||
}
|
||||
|
||||
loadFiltersFromStorage() {
|
||||
|
||||
@@ -1,24 +1,90 @@
|
||||
export const BASE_MODELS = {
|
||||
SD_1_5: "SD1.5",
|
||||
SD_2_0: "SD2.0",
|
||||
SD_2_1: "SD2.1",
|
||||
SDXL: "SDXL",
|
||||
// Stable Diffusion 1.x models
|
||||
SD_1_4: "SD 1.4",
|
||||
SD_1_5: "SD 1.5",
|
||||
SD_1_5_LCM: "SD 1.5 LCM",
|
||||
SD_1_5_HYPER: "SD 1.5 Hyper",
|
||||
|
||||
// Stable Diffusion 2.x models
|
||||
SD_2_0: "SD 2.0",
|
||||
SD_2_1: "SD 2.1",
|
||||
|
||||
// Stable Diffusion 3.x models
|
||||
SD_3: "SD 3",
|
||||
SD_3_5: "SD 3.5",
|
||||
SD_3_5_MEDIUM: "SD 3.5 Medium",
|
||||
SD_3_5_LARGE: "SD 3.5 Large",
|
||||
SD_3_5_LARGE_TURBO: "SD 3.5 Large Turbo",
|
||||
|
||||
// SDXL models
|
||||
SDXL: "SDXL 1.0",
|
||||
SDXL_LIGHTNING: "SDXL Lightning",
|
||||
SDXL_HYPER: "SDXL Hyper",
|
||||
|
||||
// Other models
|
||||
FLUX_1_D: "Flux.1 D",
|
||||
FLUX_1_S: "Flux.1 S",
|
||||
AURAFLOW: "AuraFlow",
|
||||
PIXART_A: "PixArt a",
|
||||
PIXART_E: "PixArt E",
|
||||
HUNYUAN_1: "Hunyuan 1",
|
||||
LUMINA: "Lumina",
|
||||
KOLORS: "Kolors",
|
||||
NOOBAI: "NoobAI",
|
||||
IL: "IL",
|
||||
PONY: "Pony",
|
||||
|
||||
// Video models
|
||||
SVD: "SVD",
|
||||
WAN_VIDEO: "Wan Video",
|
||||
HUNYUAN_VIDEO: "Hunyuan Video",
|
||||
|
||||
// Default
|
||||
UNKNOWN: "Unknown"
|
||||
};
|
||||
|
||||
// Base model display names and their corresponding class names (for styling)
|
||||
export const BASE_MODEL_CLASSES = {
|
||||
// Stable Diffusion 1.x models
|
||||
[BASE_MODELS.SD_1_4]: "sd-1-4",
|
||||
[BASE_MODELS.SD_1_5]: "sd-1-5",
|
||||
[BASE_MODELS.SD_1_5_LCM]: "sd-1-5-lcm",
|
||||
[BASE_MODELS.SD_1_5_HYPER]: "sd-1-5-hyper",
|
||||
|
||||
// Stable Diffusion 2.x models
|
||||
[BASE_MODELS.SD_2_0]: "sd-2-0",
|
||||
[BASE_MODELS.SD_2_1]: "sd-2-1",
|
||||
|
||||
// Stable Diffusion 3.x models
|
||||
[BASE_MODELS.SD_3]: "sd-3",
|
||||
[BASE_MODELS.SD_3_5]: "sd-3-5",
|
||||
[BASE_MODELS.SD_3_5_MEDIUM]: "sd-3-5-medium",
|
||||
[BASE_MODELS.SD_3_5_LARGE]: "sd-3-5-large",
|
||||
[BASE_MODELS.SD_3_5_LARGE_TURBO]: "sd-3-5-large-turbo",
|
||||
|
||||
// SDXL models
|
||||
[BASE_MODELS.SDXL]: "sdxl",
|
||||
[BASE_MODELS.FLUX_1_D]: "flux",
|
||||
[BASE_MODELS.SDXL_LIGHTNING]: "sdxl-lightning",
|
||||
[BASE_MODELS.SDXL_HYPER]: "sdxl-hyper",
|
||||
|
||||
// Video models
|
||||
[BASE_MODELS.SVD]: "svd",
|
||||
[BASE_MODELS.WAN_VIDEO]: "wan-video",
|
||||
[BASE_MODELS.HUNYUAN_VIDEO]: "hunyuan-video",
|
||||
|
||||
// Other models
|
||||
[BASE_MODELS.FLUX_1_D]: "flux-d",
|
||||
[BASE_MODELS.FLUX_1_S]: "flux-s",
|
||||
[BASE_MODELS.AURAFLOW]: "auraflow",
|
||||
[BASE_MODELS.PIXART_A]: "pixart-a",
|
||||
[BASE_MODELS.PIXART_E]: "pixart-e",
|
||||
[BASE_MODELS.HUNYUAN_1]: "hunyuan-1",
|
||||
[BASE_MODELS.LUMINA]: "lumina",
|
||||
[BASE_MODELS.KOLORS]: "kolors",
|
||||
[BASE_MODELS.NOOBAI]: "noobai",
|
||||
[BASE_MODELS.IL]: "il",
|
||||
[BASE_MODELS.PONY]: "pony",
|
||||
[BASE_MODELS.HUNYUAN_VIDEO]: "hunyuan",
|
||||
|
||||
// Default
|
||||
[BASE_MODELS.UNKNOWN]: "unknown"
|
||||
};
|
||||
@@ -61,8 +61,5 @@
|
||||
<button class="clear-filters-btn" onclick="filterManager.clearFilters()">
|
||||
Clear All Filters
|
||||
</button>
|
||||
<button class="apply-filters-btn" onclick="filterManager.applyFilters()">
|
||||
Apply Filters
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user