mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
Enhance recipe search functionality with improved state management and search options
- Introduced new search options for recipes, allowing users to filter by title, tags, LoRA filename, and LoRA model name. - Updated the RecipeRoutes and RecipeScanner to accommodate the new search options, enhancing the filtering capabilities. - Refactored RecipeManager and RecipeSearchManager to utilize the hierarchical state structure for managing search parameters and pagination state. - Improved the user interface by dynamically displaying relevant search options based on the current page context.
This commit is contained in:
@@ -76,6 +76,12 @@ class RecipeRoutes:
|
|||||||
sort_by = request.query.get('sort_by', 'date')
|
sort_by = request.query.get('sort_by', 'date')
|
||||||
search = request.query.get('search', None)
|
search = request.query.get('search', None)
|
||||||
|
|
||||||
|
# Get search options (renamed for better clarity)
|
||||||
|
search_title = request.query.get('search_title', 'true').lower() == 'true'
|
||||||
|
search_tags = request.query.get('search_tags', 'true').lower() == 'true'
|
||||||
|
search_lora_name = request.query.get('search_lora_name', 'true').lower() == 'true'
|
||||||
|
search_lora_model = request.query.get('search_lora_model', 'true').lower() == 'true'
|
||||||
|
|
||||||
# Get filter parameters
|
# Get filter parameters
|
||||||
base_models = request.query.get('base_models', None)
|
base_models = request.query.get('base_models', None)
|
||||||
tags = request.query.get('tags', None)
|
tags = request.query.get('tags', None)
|
||||||
@@ -87,13 +93,22 @@ class RecipeRoutes:
|
|||||||
if tags:
|
if tags:
|
||||||
filters['tags'] = tags.split(',')
|
filters['tags'] = tags.split(',')
|
||||||
|
|
||||||
|
# Add search options to filters
|
||||||
|
search_options = {
|
||||||
|
'title': search_title,
|
||||||
|
'tags': search_tags,
|
||||||
|
'lora_name': search_lora_name,
|
||||||
|
'lora_model': search_lora_model
|
||||||
|
}
|
||||||
|
|
||||||
# Get paginated data
|
# Get paginated data
|
||||||
result = await self.recipe_scanner.get_paginated_data(
|
result = await self.recipe_scanner.get_paginated_data(
|
||||||
page=page,
|
page=page,
|
||||||
page_size=page_size,
|
page_size=page_size,
|
||||||
sort_by=sort_by,
|
sort_by=sort_by,
|
||||||
search=search,
|
search=search,
|
||||||
filters=filters
|
filters=filters,
|
||||||
|
search_options=search_options
|
||||||
)
|
)
|
||||||
|
|
||||||
# Format the response data with static URLs for file paths
|
# Format the response data with static URLs for file paths
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ class RecipeScanner:
|
|||||||
logger.error(f"Error getting base model for lora: {e}")
|
logger.error(f"Error getting base model for lora: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'date', search: str = None, filters: dict = None):
|
async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'date', search: str = None, filters: dict = None, search_options: dict = None):
|
||||||
"""Get paginated and filtered recipe data
|
"""Get paginated and filtered recipe data
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -357,6 +357,7 @@ class RecipeScanner:
|
|||||||
sort_by: Sort method ('name' or 'date')
|
sort_by: Sort method ('name' or 'date')
|
||||||
search: Search term
|
search: Search term
|
||||||
filters: Dictionary of filters to apply
|
filters: Dictionary of filters to apply
|
||||||
|
search_options: Dictionary of search options to apply
|
||||||
"""
|
"""
|
||||||
cache = await self.get_cached_data()
|
cache = await self.get_cached_data()
|
||||||
|
|
||||||
@@ -365,11 +366,44 @@ class RecipeScanner:
|
|||||||
|
|
||||||
# Apply search filter
|
# Apply search filter
|
||||||
if search:
|
if search:
|
||||||
filtered_data = [
|
# Default search options if none provided
|
||||||
item for item in filtered_data
|
if not search_options:
|
||||||
if search.lower() in str(item.get('title', '')).lower() or
|
search_options = {
|
||||||
search.lower() in str(item.get('prompt', '')).lower()
|
'title': True,
|
||||||
]
|
'tags': True,
|
||||||
|
'lora_name': True,
|
||||||
|
'lora_model': True
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build the search predicate based on search options
|
||||||
|
def matches_search(item):
|
||||||
|
# Search in title if enabled
|
||||||
|
if search_options.get('title', True) and search.lower() in str(item.get('title', '')).lower():
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Search in tags if enabled
|
||||||
|
if search_options.get('tags', True) and 'tags' in item:
|
||||||
|
for tag in item['tags']:
|
||||||
|
if search.lower() in tag.lower():
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Search in lora file names if enabled
|
||||||
|
if search_options.get('lora_name', True) and 'loras' in item:
|
||||||
|
for lora in item['loras']:
|
||||||
|
if search.lower() in str(lora.get('file_name', '')).lower():
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Search in lora model names if enabled
|
||||||
|
if search_options.get('lora_model', True) and 'loras' in item:
|
||||||
|
for lora in item['loras']:
|
||||||
|
if search.lower() in str(lora.get('modelName', '')).lower():
|
||||||
|
return True
|
||||||
|
|
||||||
|
# No match found
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Filter the data using the search predicate
|
||||||
|
filtered_data = [item for item in filtered_data if matches_search(item)]
|
||||||
|
|
||||||
# Apply additional filters
|
# Apply additional filters
|
||||||
if filters:
|
if filters:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Extends the base SearchManager with recipe-specific functionality
|
* Extends the base SearchManager with recipe-specific functionality
|
||||||
*/
|
*/
|
||||||
import { SearchManager } from './SearchManager.js';
|
import { SearchManager } from './SearchManager.js';
|
||||||
import { state } from '../state/index.js';
|
import { state, getCurrentPageState } from '../state/index.js';
|
||||||
import { showToast } from '../utils/uiHelpers.js';
|
import { showToast } from '../utils/uiHelpers.js';
|
||||||
|
|
||||||
export class RecipeSearchManager extends SearchManager {
|
export class RecipeSearchManager extends SearchManager {
|
||||||
@@ -17,7 +17,7 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
|
|
||||||
// Store this instance in the state
|
// Store this instance in the state
|
||||||
if (state) {
|
if (state) {
|
||||||
state.searchManager = this;
|
state.pages.recipes.searchManager = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
|
|
||||||
if (!searchTerm) {
|
if (!searchTerm) {
|
||||||
if (state) {
|
if (state) {
|
||||||
state.currentPage = 1;
|
state.pages.recipes.currentPage = 1;
|
||||||
}
|
}
|
||||||
this.resetAndReloadRecipes();
|
this.resetAndReloadRecipes();
|
||||||
return;
|
return;
|
||||||
@@ -50,22 +50,24 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
state.currentPage = 1;
|
state.pages.recipes.currentPage = 1;
|
||||||
state.hasMore = true;
|
state.pages.recipes.hasMore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL('/api/recipes', window.location.origin);
|
const url = new URL('/api/recipes', window.location.origin);
|
||||||
url.searchParams.set('page', '1');
|
url.searchParams.set('page', '1');
|
||||||
url.searchParams.set('page_size', '20');
|
url.searchParams.set('page_size', '20');
|
||||||
url.searchParams.set('sort_by', state ? state.sortBy : 'name');
|
url.searchParams.set('sort_by', state ? state.pages.recipes.sortBy : 'name');
|
||||||
url.searchParams.set('search', searchTerm);
|
url.searchParams.set('search', searchTerm);
|
||||||
url.searchParams.set('fuzzy', 'true');
|
url.searchParams.set('fuzzy', 'true');
|
||||||
|
|
||||||
// Add search options
|
// Add search options
|
||||||
const searchOptions = this.getActiveSearchOptions();
|
const recipeState = getCurrentPageState();
|
||||||
url.searchParams.set('search_name', searchOptions.modelname.toString());
|
const searchOptions = recipeState.searchOptions;
|
||||||
|
url.searchParams.set('search_title', searchOptions.title.toString());
|
||||||
url.searchParams.set('search_tags', searchOptions.tags.toString());
|
url.searchParams.set('search_tags', searchOptions.tags.toString());
|
||||||
url.searchParams.set('search_loras', searchOptions.loras.toString());
|
url.searchParams.set('search_lora_name', searchOptions.loraName.toString());
|
||||||
|
url.searchParams.set('search_lora_model', searchOptions.loraModel.toString());
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
|
|
||||||
@@ -81,13 +83,13 @@ export class RecipeSearchManager extends SearchManager {
|
|||||||
if (data.items.length === 0) {
|
if (data.items.length === 0) {
|
||||||
grid.innerHTML = '<div class="no-results">No matching recipes found</div>';
|
grid.innerHTML = '<div class="no-results">No matching recipes found</div>';
|
||||||
if (state) {
|
if (state) {
|
||||||
state.hasMore = false;
|
state.pages.recipes.hasMore = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.appendRecipeCards(data.items);
|
this.appendRecipeCards(data.items);
|
||||||
if (state) {
|
if (state) {
|
||||||
state.hasMore = state.currentPage < data.total_pages;
|
state.pages.recipes.hasMore = state.pages.recipes.currentPage < data.total_pages;
|
||||||
state.currentPage++;
|
state.pages.recipes.currentPage++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class SearchManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply recursive search
|
// Apply recursive search - only if the toggle exists
|
||||||
if (this.recursiveSearchToggle && preferences.recursive !== undefined) {
|
if (this.recursiveSearchToggle && preferences.recursive !== undefined) {
|
||||||
this.recursiveSearchToggle.checked = preferences.recursive;
|
this.recursiveSearchToggle.checked = preferences.recursive;
|
||||||
}
|
}
|
||||||
@@ -245,10 +245,14 @@ export class SearchManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const preferences = {
|
const preferences = {
|
||||||
options,
|
options
|
||||||
recursive: this.recursiveSearchToggle ? this.recursiveSearchToggle.checked : false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only add recursive option if the toggle exists
|
||||||
|
if (this.recursiveSearchToggle) {
|
||||||
|
preferences.recursive = this.recursiveSearchToggle.checked;
|
||||||
|
}
|
||||||
|
|
||||||
localStorage.setItem(`${this.currentPage}_search_prefs`, JSON.stringify(preferences));
|
localStorage.setItem(`${this.currentPage}_search_prefs`, JSON.stringify(preferences));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving search preferences:', error);
|
console.error('Error saving search preferences:', error);
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import { appCore } from './core.js';
|
|||||||
import { ImportManager } from './managers/ImportManager.js';
|
import { ImportManager } from './managers/ImportManager.js';
|
||||||
import { RecipeCard } from './components/RecipeCard.js';
|
import { RecipeCard } from './components/RecipeCard.js';
|
||||||
import { RecipeModal } from './components/RecipeModal.js';
|
import { RecipeModal } from './components/RecipeModal.js';
|
||||||
|
import { state, getCurrentPageState, setCurrentPageType, initPageState } from './state/index.js';
|
||||||
|
|
||||||
class RecipeManager {
|
class RecipeManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.currentPage = 1;
|
// Initialize recipe page state
|
||||||
this.pageSize = 20;
|
initPageState('recipes');
|
||||||
this.sortBy = 'date';
|
|
||||||
this.filterParams = {};
|
// Get page state
|
||||||
|
this.pageState = getCurrentPageState();
|
||||||
|
|
||||||
// Initialize ImportManager
|
// Initialize ImportManager
|
||||||
this.importManager = new ImportManager();
|
this.importManager = new ImportManager();
|
||||||
@@ -18,14 +20,17 @@ class RecipeManager {
|
|||||||
this.recipeModal = new RecipeModal();
|
this.recipeModal = new RecipeModal();
|
||||||
|
|
||||||
// Add state tracking for infinite scroll
|
// Add state tracking for infinite scroll
|
||||||
this.isLoading = false;
|
this.pageState.isLoading = false;
|
||||||
this.hasMore = true;
|
this.pageState.hasMore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
// Initialize event listeners
|
// Initialize event listeners
|
||||||
this.initEventListeners();
|
this.initEventListeners();
|
||||||
|
|
||||||
|
// Set default search options if not already defined
|
||||||
|
this._initSearchOptions();
|
||||||
|
|
||||||
// Load initial set of recipes
|
// Load initial set of recipes
|
||||||
await this.loadRecipes();
|
await this.loadRecipes();
|
||||||
|
|
||||||
@@ -36,6 +41,18 @@ class RecipeManager {
|
|||||||
appCore.initializePageFeatures();
|
appCore.initializePageFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_initSearchOptions() {
|
||||||
|
// Ensure recipes search options are properly initialized
|
||||||
|
if (!this.pageState.searchOptions) {
|
||||||
|
this.pageState.searchOptions = {
|
||||||
|
title: true, // Recipe title
|
||||||
|
tags: true, // Recipe tags
|
||||||
|
loraName: true, // LoRA file name
|
||||||
|
loraModel: true // LoRA model name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_exposeGlobalFunctions() {
|
_exposeGlobalFunctions() {
|
||||||
// Only expose what's needed for the page
|
// Only expose what's needed for the page
|
||||||
window.recipeManager = this;
|
window.recipeManager = this;
|
||||||
@@ -49,7 +66,7 @@ class RecipeManager {
|
|||||||
const sortSelect = document.getElementById('sortSelect');
|
const sortSelect = document.getElementById('sortSelect');
|
||||||
if (sortSelect) {
|
if (sortSelect) {
|
||||||
sortSelect.addEventListener('change', () => {
|
sortSelect.addEventListener('change', () => {
|
||||||
this.sortBy = sortSelect.value;
|
this.pageState.sortBy = sortSelect.value;
|
||||||
this.loadRecipes();
|
this.loadRecipes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -61,7 +78,7 @@ class RecipeManager {
|
|||||||
searchInput.addEventListener('input', () => {
|
searchInput.addEventListener('input', () => {
|
||||||
clearTimeout(debounceTimeout);
|
clearTimeout(debounceTimeout);
|
||||||
debounceTimeout = setTimeout(() => {
|
debounceTimeout = setTimeout(() => {
|
||||||
this.filterParams.search = searchInput.value;
|
this.pageState.filters.search = searchInput.value;
|
||||||
this.loadRecipes();
|
this.loadRecipes();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
@@ -81,11 +98,11 @@ class RecipeManager {
|
|||||||
try {
|
try {
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
document.body.classList.add('loading');
|
document.body.classList.add('loading');
|
||||||
this.isLoading = true;
|
this.pageState.isLoading = true;
|
||||||
|
|
||||||
// Reset to first page if requested
|
// Reset to first page if requested
|
||||||
if (resetPage) {
|
if (resetPage) {
|
||||||
this.currentPage = 1;
|
this.pageState.currentPage = 1;
|
||||||
// Clear grid if resetting
|
// Clear grid if resetting
|
||||||
const grid = document.getElementById('recipeGrid');
|
const grid = document.getElementById('recipeGrid');
|
||||||
if (grid) grid.innerHTML = '';
|
if (grid) grid.innerHTML = '';
|
||||||
@@ -93,19 +110,24 @@ class RecipeManager {
|
|||||||
|
|
||||||
// Build query parameters
|
// Build query parameters
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
page: this.currentPage,
|
page: this.pageState.currentPage,
|
||||||
page_size: this.pageSize,
|
page_size: this.pageState.pageSize || 20,
|
||||||
sort_by: this.sortBy
|
sort_by: this.pageState.sortBy
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add search filter if present
|
// Add search filter if present
|
||||||
if (this.filterParams.search) {
|
if (this.pageState.filters.search) {
|
||||||
params.append('search', this.filterParams.search);
|
params.append('search', this.pageState.filters.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add other filters
|
// Add base model filters
|
||||||
if (this.filterParams.baseModels && this.filterParams.baseModels.length) {
|
if (this.pageState.filters.baseModel && this.pageState.filters.baseModel.length) {
|
||||||
params.append('base_models', this.filterParams.baseModels.join(','));
|
params.append('base_models', this.pageState.filters.baseModel.join(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add tag filters
|
||||||
|
if (this.pageState.filters.tags && this.pageState.filters.tags.length) {
|
||||||
|
params.append('tags', this.pageState.filters.tags.join(','));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch recipes
|
// Fetch recipes
|
||||||
@@ -121,7 +143,7 @@ class RecipeManager {
|
|||||||
this.updateRecipesGrid(data, resetPage);
|
this.updateRecipesGrid(data, resetPage);
|
||||||
|
|
||||||
// Update pagination state
|
// Update pagination state
|
||||||
this.hasMore = data.has_more || false;
|
this.pageState.hasMore = data.has_more || false;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading recipes:', error);
|
console.error('Error loading recipes:', error);
|
||||||
@@ -129,15 +151,15 @@ class RecipeManager {
|
|||||||
} finally {
|
} finally {
|
||||||
// Hide loading indicator
|
// Hide loading indicator
|
||||||
document.body.classList.remove('loading');
|
document.body.classList.remove('loading');
|
||||||
this.isLoading = false;
|
this.pageState.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load more recipes for infinite scroll
|
// Load more recipes for infinite scroll
|
||||||
async loadMoreRecipes() {
|
async loadMoreRecipes() {
|
||||||
if (this.isLoading || !this.hasMore) return;
|
if (this.pageState.isLoading || !this.pageState.hasMore) return;
|
||||||
|
|
||||||
this.currentPage++;
|
this.pageState.currentPage++;
|
||||||
await this.loadRecipes(false);
|
await this.loadRecipes(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +192,7 @@ class RecipeManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add sentinel for infinite scroll if needed
|
// Add sentinel for infinite scroll if needed
|
||||||
if (this.hasMore) {
|
if (this.pageState.hasMore) {
|
||||||
let sentinel = document.getElementById('scroll-sentinel');
|
let sentinel = document.getElementById('scroll-sentinel');
|
||||||
if (!sentinel) {
|
if (!sentinel) {
|
||||||
sentinel = document.createElement('div');
|
sentinel = document.createElement('div');
|
||||||
@@ -179,8 +201,8 @@ class RecipeManager {
|
|||||||
grid.appendChild(sentinel);
|
grid.appendChild(sentinel);
|
||||||
|
|
||||||
// Re-observe the sentinel if we have an observer
|
// Re-observe the sentinel if we have an observer
|
||||||
if (window.state && window.state.observer) {
|
if (state && state.observer) {
|
||||||
window.state.observer.observe(sentinel);
|
state.observer.observe(sentinel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,16 +42,17 @@ export const state = {
|
|||||||
sortBy: 'date',
|
sortBy: 'date',
|
||||||
searchManager: null,
|
searchManager: null,
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
filename: true,
|
title: true,
|
||||||
modelname: true,
|
|
||||||
tags: true,
|
tags: true,
|
||||||
loras: true,
|
loraName: true,
|
||||||
recursive: false
|
loraModel: true
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
baseModel: [],
|
baseModel: [],
|
||||||
tags: []
|
tags: [],
|
||||||
}
|
search: ''
|
||||||
|
},
|
||||||
|
pageSize: 20
|
||||||
},
|
},
|
||||||
|
|
||||||
checkpoints: {
|
checkpoints: {
|
||||||
|
|||||||
@@ -66,18 +66,23 @@
|
|||||||
<div class="options-section">
|
<div class="options-section">
|
||||||
<h4>Search In:</h4>
|
<h4>Search In:</h4>
|
||||||
<div class="search-option-tags">
|
<div class="search-option-tags">
|
||||||
<div class="search-option-tag active" data-option="filename">Filename</div>
|
|
||||||
{% if request.path == '/loras' or request.path == '/loras/recipes' %}
|
|
||||||
<div class="search-option-tag active" data-option="tags">Tags</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="search-option-tag active" data-option="modelname">
|
|
||||||
{% if request.path == '/loras/recipes' %}Recipe Name{% elif request.path == '/checkpoints' %}Checkpoint Name{% else %}Model Name{% endif %}
|
|
||||||
</div>
|
|
||||||
{% if request.path == '/loras/recipes' %}
|
{% if request.path == '/loras/recipes' %}
|
||||||
<div class="search-option-tag active" data-option="loras">Included LoRAs</div>
|
<div class="search-option-tag active" data-option="title">Recipe Title</div>
|
||||||
|
<div class="search-option-tag active" data-option="tags">Tags</div>
|
||||||
|
<div class="search-option-tag active" data-option="loraName">LoRA Filename</div>
|
||||||
|
<div class="search-option-tag active" data-option="loraModel">LoRA Model Name</div>
|
||||||
|
{% elif request.path == '/checkpoints' %}
|
||||||
|
<div class="search-option-tag active" data-option="filename">Filename</div>
|
||||||
|
<div class="search-option-tag active" data-option="modelname">Checkpoint Name</div>
|
||||||
|
{% else %}
|
||||||
|
<!-- Default options for LoRAs page -->
|
||||||
|
<div class="search-option-tag active" data-option="filename">Filename</div>
|
||||||
|
<div class="search-option-tag active" data-option="modelname">Model Name</div>
|
||||||
|
<div class="search-option-tag active" data-option="tags">Tags</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if request.path != '/loras/recipes' %}
|
||||||
<div class="options-section">
|
<div class="options-section">
|
||||||
<div class="search-option-switch">
|
<div class="search-option-switch">
|
||||||
<span>Include Subfolders</span>
|
<span>Include Subfolders</span>
|
||||||
@@ -87,6 +92,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Add filter panel -->
|
<!-- Add filter panel -->
|
||||||
|
|||||||
Reference in New Issue
Block a user