Add filters - base model only for now

This commit is contained in:
Will Miao
2025-03-05 19:53:52 +08:00
parent c17f2c885a
commit f614dbf700
9 changed files with 139 additions and 47 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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",

View File

@@ -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 {

View File

@@ -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());

View File

@@ -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();

View File

@@ -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() {

View File

@@ -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"
};

View File

@@ -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>