mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
feat: Update recipes page with default descending date sort, refactor state properties for search/filters, and add new localization strings.
This commit is contained in:
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "Bitte wählen Sie ein LoRA-Stammverzeichnis aus"
|
"selectLoraRoot": "Bitte wählen Sie ein LoRA-Stammverzeichnis aus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "Rezepte sortieren nach...",
|
||||||
|
"name": "Name",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "Datum",
|
||||||
|
"dateDesc": "Neueste",
|
||||||
|
"dateAsc": "Älteste",
|
||||||
|
"lorasCount": "LoRA-Anzahl",
|
||||||
|
"lorasCountDesc": "Meiste",
|
||||||
|
"lorasCountAsc": "Wenigste"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "Rezeptliste aktualisieren"
|
"title": "Rezeptliste aktualisieren"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "Please select a LoRA root directory"
|
"selectLoraRoot": "Please select a LoRA root directory"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "Sort recipes by...",
|
||||||
|
"name": "Name",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "Date",
|
||||||
|
"dateDesc": "Newest",
|
||||||
|
"dateAsc": "Oldest",
|
||||||
|
"lorasCount": "LoRA Count",
|
||||||
|
"lorasCountDesc": "Most",
|
||||||
|
"lorasCountAsc": "Least"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "Refresh recipe list"
|
"title": "Refresh recipe list"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "Por favor selecciona un directorio raíz de LoRA"
|
"selectLoraRoot": "Por favor selecciona un directorio raíz de LoRA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "Ordenar recetas por...",
|
||||||
|
"name": "Nombre",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "Fecha",
|
||||||
|
"dateDesc": "Más reciente",
|
||||||
|
"dateAsc": "Más antiguo",
|
||||||
|
"lorasCount": "Cant. de LoRAs",
|
||||||
|
"lorasCountDesc": "Más",
|
||||||
|
"lorasCountAsc": "Menos"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "Actualizar lista de recetas"
|
"title": "Actualizar lista de recetas"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "Veuillez sélectionner un répertoire racine LoRA"
|
"selectLoraRoot": "Veuillez sélectionner un répertoire racine LoRA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "Trier les recettes par...",
|
||||||
|
"name": "Nom",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "Date",
|
||||||
|
"dateDesc": "Plus récent",
|
||||||
|
"dateAsc": "Plus ancien",
|
||||||
|
"lorasCount": "Nombre de LoRAs",
|
||||||
|
"lorasCountDesc": "Plus",
|
||||||
|
"lorasCountAsc": "Moins"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "Actualiser la liste des recipes"
|
"title": "Actualiser la liste des recipes"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "אנא בחר ספריית שורש של LoRA"
|
"selectLoraRoot": "אנא בחר ספריית שורש של LoRA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "מיון מתכונים לפי...",
|
||||||
|
"name": "שם",
|
||||||
|
"nameAsc": "א - ת",
|
||||||
|
"nameDesc": "ת - א",
|
||||||
|
"date": "תאריך",
|
||||||
|
"dateDesc": "הכי חדש",
|
||||||
|
"dateAsc": "הכי ישן",
|
||||||
|
"lorasCount": "מספר LoRAs",
|
||||||
|
"lorasCountDesc": "הכי הרבה",
|
||||||
|
"lorasCountAsc": "הכי פחות"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "רענן רשימת מתכונים"
|
"title": "רענן רשימת מתכונים"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "LoRAルートディレクトリを選択してください"
|
"selectLoraRoot": "LoRAルートディレクトリを選択してください"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "レシピの並び替え...",
|
||||||
|
"name": "名前",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "日付",
|
||||||
|
"dateDesc": "新しい順",
|
||||||
|
"dateAsc": "古い順",
|
||||||
|
"lorasCount": "LoRA数",
|
||||||
|
"lorasCountDesc": "多い順",
|
||||||
|
"lorasCountAsc": "少ない順"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "レシピリストを更新"
|
"title": "レシピリストを更新"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "LoRA 루트 디렉토리를 선택해주세요"
|
"selectLoraRoot": "LoRA 루트 디렉토리를 선택해주세요"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "레시피 정렬...",
|
||||||
|
"name": "이름",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "날짜",
|
||||||
|
"dateDesc": "최신순",
|
||||||
|
"dateAsc": "오래된순",
|
||||||
|
"lorasCount": "LoRA 수",
|
||||||
|
"lorasCountDesc": "많은순",
|
||||||
|
"lorasCountAsc": "적은순"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "레시피 목록 새로고침"
|
"title": "레시피 목록 새로고침"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "Пожалуйста, выберите корневую папку LoRA"
|
"selectLoraRoot": "Пожалуйста, выберите корневую папку LoRA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "Сортировка рецептов...",
|
||||||
|
"name": "Имя",
|
||||||
|
"nameAsc": "А - Я",
|
||||||
|
"nameDesc": "Я - А",
|
||||||
|
"date": "Дата",
|
||||||
|
"dateDesc": "Сначала новые",
|
||||||
|
"dateAsc": "Сначала старые",
|
||||||
|
"lorasCount": "Кол-во LoRA",
|
||||||
|
"lorasCountDesc": "Больше всего",
|
||||||
|
"lorasCountAsc": "Меньше всего"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "Обновить список рецептов"
|
"title": "Обновить список рецептов"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "请选择 LoRA 根目录"
|
"selectLoraRoot": "请选择 LoRA 根目录"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "配方排序...",
|
||||||
|
"name": "名称",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "时间",
|
||||||
|
"dateDesc": "最新",
|
||||||
|
"dateAsc": "最早",
|
||||||
|
"lorasCount": "LoRA 数量",
|
||||||
|
"lorasCountDesc": "最多",
|
||||||
|
"lorasCountAsc": "最少"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "刷新配方列表"
|
"title": "刷新配方列表"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "浏览器插件教程"
|
"learnMore": "浏览器插件教程"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,18 @@
|
|||||||
"selectLoraRoot": "請選擇 LoRA 根目錄"
|
"selectLoraRoot": "請選擇 LoRA 根目錄"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort": {
|
||||||
|
"title": "配方排序...",
|
||||||
|
"name": "名稱",
|
||||||
|
"nameAsc": "A - Z",
|
||||||
|
"nameDesc": "Z - A",
|
||||||
|
"date": "時間",
|
||||||
|
"dateDesc": "最新",
|
||||||
|
"dateAsc": "最舊",
|
||||||
|
"lorasCount": "LoRA 數量",
|
||||||
|
"lorasCountDesc": "最多",
|
||||||
|
"lorasCountAsc": "最少"
|
||||||
|
},
|
||||||
"refresh": {
|
"refresh": {
|
||||||
"title": "重新整理配方列表"
|
"title": "重新整理配方列表"
|
||||||
},
|
},
|
||||||
@@ -1485,4 +1497,4 @@
|
|||||||
"learnMore": "LM Civitai Extension Tutorial"
|
"learnMore": "LM Civitai Extension Tutorial"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1024,7 +1024,14 @@ class RecipeScanner:
|
|||||||
cache = await self.get_cached_data()
|
cache = await self.get_cached_data()
|
||||||
|
|
||||||
# Get base dataset
|
# Get base dataset
|
||||||
filtered_data = cache.sorted_by_date if sort_by == 'date' else cache.sorted_by_name
|
sort_field = sort_by.split(':')[0] if ':' in sort_by else sort_by
|
||||||
|
|
||||||
|
if sort_field == 'date':
|
||||||
|
filtered_data = list(cache.sorted_by_date)
|
||||||
|
elif sort_field == 'name':
|
||||||
|
filtered_data = list(cache.sorted_by_name)
|
||||||
|
else:
|
||||||
|
filtered_data = list(cache.raw_data)
|
||||||
|
|
||||||
# Apply SFW filtering if enabled
|
# Apply SFW filtering if enabled
|
||||||
from .settings_manager import get_settings_manager
|
from .settings_manager import get_settings_manager
|
||||||
@@ -1166,6 +1173,20 @@ class RecipeScanner:
|
|||||||
if not any(tag in exclude_tags for tag in (item.get('tags', []) or []))
|
if not any(tag in exclude_tags for tag in (item.get('tags', []) or []))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Apply sorting if not already handled by pre-sorted cache
|
||||||
|
if ':' in sort_by or sort_field == 'loras_count':
|
||||||
|
field, order = (sort_by.split(':') + ['desc'])[:2]
|
||||||
|
reverse = order.lower() == 'desc'
|
||||||
|
|
||||||
|
if field == 'name':
|
||||||
|
filtered_data = natsorted(filtered_data, key=lambda x: x.get('title', '').lower(), reverse=reverse)
|
||||||
|
elif field == 'date':
|
||||||
|
# Use modified if available, falling back to created_date
|
||||||
|
filtered_data.sort(key=lambda x: (x.get('modified', x.get('created_date', 0)), x.get('file_path', '')), reverse=reverse)
|
||||||
|
elif field == 'loras_count':
|
||||||
|
filtered_data.sort(key=lambda x: len(x.get('loras', [])), reverse=reverse)
|
||||||
|
|
||||||
# Calculate pagination
|
# Calculate pagination
|
||||||
total_items = len(filtered_data)
|
total_items = len(filtered_data)
|
||||||
start_idx = (page - 1) * page_size
|
start_idx = (page - 1) * page_size
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ class RecipeManager {
|
|||||||
// Sort select
|
// Sort select
|
||||||
const sortSelect = document.getElementById('sortSelect');
|
const sortSelect = document.getElementById('sortSelect');
|
||||||
if (sortSelect) {
|
if (sortSelect) {
|
||||||
|
sortSelect.value = this.pageState.sortBy || 'date:desc';
|
||||||
sortSelect.addEventListener('change', () => {
|
sortSelect.addEventListener('change', () => {
|
||||||
this.pageState.sortBy = sortSelect.value;
|
this.pageState.sortBy = sortSelect.value;
|
||||||
refreshVirtualScroll();
|
refreshVirtualScroll();
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const state = {
|
|||||||
loadingManager: null,
|
loadingManager: null,
|
||||||
observer: null,
|
observer: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Page-specific states
|
// Page-specific states
|
||||||
pages: {
|
pages: {
|
||||||
[MODEL_TYPES.LORA]: {
|
[MODEL_TYPES.LORA]: {
|
||||||
@@ -69,20 +69,20 @@ export const state = {
|
|||||||
activeFolder: getStorageItem(`${MODEL_TYPES.LORA}_activeFolder`),
|
activeFolder: getStorageItem(`${MODEL_TYPES.LORA}_activeFolder`),
|
||||||
activeLetterFilter: null,
|
activeLetterFilter: null,
|
||||||
previewVersions: loraPreviewVersions,
|
previewVersions: loraPreviewVersions,
|
||||||
searchManager: null,
|
searchManager: null,
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
filename: true,
|
filename: true,
|
||||||
modelname: true,
|
modelname: true,
|
||||||
tags: false,
|
tags: false,
|
||||||
creator: false,
|
creator: false,
|
||||||
recursive: getStorageItem(`${MODEL_TYPES.LORA}_recursiveSearch`, true),
|
recursive: getStorageItem(`${MODEL_TYPES.LORA}_recursiveSearch`, true),
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
baseModel: [],
|
baseModel: [],
|
||||||
tags: {},
|
tags: {},
|
||||||
license: {},
|
license: {},
|
||||||
modelTypes: []
|
modelTypes: []
|
||||||
},
|
},
|
||||||
bulkMode: false,
|
bulkMode: false,
|
||||||
selectedLoras: new Set(),
|
selectedLoras: new Set(),
|
||||||
loraMetadataCache: new Map(),
|
loraMetadataCache: new Map(),
|
||||||
@@ -90,35 +90,35 @@ export const state = {
|
|||||||
showUpdateAvailableOnly: false,
|
showUpdateAvailableOnly: false,
|
||||||
duplicatesMode: false,
|
duplicatesMode: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
recipes: {
|
recipes: {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
hasMore: true,
|
hasMore: true,
|
||||||
sortBy: 'date',
|
sortBy: 'date:desc',
|
||||||
activeFolder: getStorageItem('recipes_activeFolder'),
|
activeFolder: getStorageItem('recipes_activeFolder'),
|
||||||
searchManager: null,
|
searchManager: null,
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
title: true,
|
title: true,
|
||||||
tags: true,
|
tags: true,
|
||||||
loraName: true,
|
loraName: true,
|
||||||
loraModel: true,
|
loraModel: true,
|
||||||
recursive: getStorageItem('recipes_recursiveSearch', true),
|
recursive: getStorageItem('recipes_recursiveSearch', true),
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
baseModel: [],
|
baseModel: [],
|
||||||
tags: {},
|
tags: {},
|
||||||
license: {},
|
license: {},
|
||||||
modelTypes: [],
|
modelTypes: [],
|
||||||
search: ''
|
search: ''
|
||||||
},
|
},
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
showFavoritesOnly: false,
|
showFavoritesOnly: false,
|
||||||
duplicatesMode: false,
|
duplicatesMode: false,
|
||||||
bulkMode: false,
|
bulkMode: false,
|
||||||
selectedModels: new Set(),
|
selectedModels: new Set(),
|
||||||
},
|
},
|
||||||
|
|
||||||
[MODEL_TYPES.CHECKPOINT]: {
|
[MODEL_TYPES.CHECKPOINT]: {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@@ -126,19 +126,19 @@ export const state = {
|
|||||||
sortBy: 'name',
|
sortBy: 'name',
|
||||||
activeFolder: getStorageItem(`${MODEL_TYPES.CHECKPOINT}_activeFolder`),
|
activeFolder: getStorageItem(`${MODEL_TYPES.CHECKPOINT}_activeFolder`),
|
||||||
previewVersions: checkpointPreviewVersions,
|
previewVersions: checkpointPreviewVersions,
|
||||||
searchManager: null,
|
searchManager: null,
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
filename: true,
|
filename: true,
|
||||||
modelname: true,
|
modelname: true,
|
||||||
creator: false,
|
creator: false,
|
||||||
recursive: getStorageItem(`${MODEL_TYPES.CHECKPOINT}_recursiveSearch`, true),
|
recursive: getStorageItem(`${MODEL_TYPES.CHECKPOINT}_recursiveSearch`, true),
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
baseModel: [],
|
baseModel: [],
|
||||||
tags: {},
|
tags: {},
|
||||||
license: {},
|
license: {},
|
||||||
modelTypes: []
|
modelTypes: []
|
||||||
},
|
},
|
||||||
modelType: 'checkpoint', // 'checkpoint' or 'diffusion_model'
|
modelType: 'checkpoint', // 'checkpoint' or 'diffusion_model'
|
||||||
bulkMode: false,
|
bulkMode: false,
|
||||||
selectedModels: new Set(),
|
selectedModels: new Set(),
|
||||||
@@ -147,7 +147,7 @@ export const state = {
|
|||||||
showUpdateAvailableOnly: false,
|
showUpdateAvailableOnly: false,
|
||||||
duplicatesMode: false,
|
duplicatesMode: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
[MODEL_TYPES.EMBEDDING]: {
|
[MODEL_TYPES.EMBEDDING]: {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@@ -156,20 +156,20 @@ export const state = {
|
|||||||
activeFolder: getStorageItem(`${MODEL_TYPES.EMBEDDING}_activeFolder`),
|
activeFolder: getStorageItem(`${MODEL_TYPES.EMBEDDING}_activeFolder`),
|
||||||
activeLetterFilter: null,
|
activeLetterFilter: null,
|
||||||
previewVersions: embeddingPreviewVersions,
|
previewVersions: embeddingPreviewVersions,
|
||||||
searchManager: null,
|
searchManager: null,
|
||||||
searchOptions: {
|
searchOptions: {
|
||||||
filename: true,
|
filename: true,
|
||||||
modelname: true,
|
modelname: true,
|
||||||
tags: false,
|
tags: false,
|
||||||
creator: false,
|
creator: false,
|
||||||
recursive: getStorageItem(`${MODEL_TYPES.EMBEDDING}_recursiveSearch`, true),
|
recursive: getStorageItem(`${MODEL_TYPES.EMBEDDING}_recursiveSearch`, true),
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
baseModel: [],
|
baseModel: [],
|
||||||
tags: {},
|
tags: {},
|
||||||
license: {},
|
license: {},
|
||||||
modelTypes: []
|
modelTypes: []
|
||||||
},
|
},
|
||||||
bulkMode: false,
|
bulkMode: false,
|
||||||
selectedModels: new Set(),
|
selectedModels: new Set(),
|
||||||
metadataCache: new Map(),
|
metadataCache: new Map(),
|
||||||
@@ -178,45 +178,45 @@ export const state = {
|
|||||||
duplicatesMode: false,
|
duplicatesMode: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Current active page - use MODEL_TYPES constants
|
// Current active page - use MODEL_TYPES constants
|
||||||
currentPageType: MODEL_TYPES.LORA,
|
currentPageType: MODEL_TYPES.LORA,
|
||||||
|
|
||||||
// Backward compatibility - proxy properties
|
// Backward compatibility - proxy properties
|
||||||
get currentPage() { return this.pages[this.currentPageType].currentPage; },
|
get currentPage() { return this.pages[this.currentPageType].currentPage; },
|
||||||
set currentPage(value) { this.pages[this.currentPageType].currentPage = value; },
|
set currentPage(value) { this.pages[this.currentPageType].currentPage = value; },
|
||||||
|
|
||||||
get isLoading() { return this.pages[this.currentPageType].isLoading; },
|
get isLoading() { return this.pages[this.currentPageType].isLoading; },
|
||||||
set isLoading(value) { this.pages[this.currentPageType].isLoading = value; },
|
set isLoading(value) { this.pages[this.currentPageType].isLoading = value; },
|
||||||
|
|
||||||
get hasMore() { return this.pages[this.currentPageType].hasMore; },
|
get hasMore() { return this.pages[this.currentPageType].hasMore; },
|
||||||
set hasMore(value) { this.pages[this.currentPageType].hasMore = value; },
|
set hasMore(value) { this.pages[this.currentPageType].hasMore = value; },
|
||||||
|
|
||||||
get sortBy() { return this.pages[this.currentPageType].sortBy; },
|
get sortBy() { return this.pages[this.currentPageType].sortBy; },
|
||||||
set sortBy(value) { this.pages[this.currentPageType].sortBy = value; },
|
set sortBy(value) { this.pages[this.currentPageType].sortBy = value; },
|
||||||
|
|
||||||
get activeFolder() { return this.pages[this.currentPageType].activeFolder; },
|
get activeFolder() { return this.pages[this.currentPageType].activeFolder; },
|
||||||
set activeFolder(value) { this.pages[this.currentPageType].activeFolder = value; },
|
set activeFolder(value) { this.pages[this.currentPageType].activeFolder = value; },
|
||||||
|
|
||||||
get loadingManager() { return this.global.loadingManager; },
|
get loadingManager() { return this.global.loadingManager; },
|
||||||
set loadingManager(value) { this.global.loadingManager = value; },
|
set loadingManager(value) { this.global.loadingManager = value; },
|
||||||
|
|
||||||
get observer() { return this.global.observer; },
|
get observer() { return this.global.observer; },
|
||||||
set observer(value) { this.global.observer = value; },
|
set observer(value) { this.global.observer = value; },
|
||||||
|
|
||||||
get previewVersions() { return this.pages.loras.previewVersions; },
|
get previewVersions() { return this.pages.loras.previewVersions; },
|
||||||
set previewVersions(value) { this.pages.loras.previewVersions = value; },
|
set previewVersions(value) { this.pages.loras.previewVersions = value; },
|
||||||
|
|
||||||
get searchManager() { return this.pages[this.currentPageType].searchManager; },
|
get searchManager() { return this.pages[this.currentPageType].searchManager; },
|
||||||
set searchManager(value) { this.pages[this.currentPageType].searchManager = value; },
|
set searchManager(value) { this.pages[this.currentPageType].searchManager = value; },
|
||||||
|
|
||||||
get searchOptions() { return this.pages[this.currentPageType].searchOptions; },
|
get searchOptions() { return this.pages[this.currentPageType].searchOptions; },
|
||||||
set searchOptions(value) { this.pages[this.currentPageType].searchOptions = value; },
|
set searchOptions(value) { this.pages[this.currentPageType].searchOptions = value; },
|
||||||
|
|
||||||
get filters() { return this.pages[this.currentPageType].filters; },
|
get filters() { return this.pages[this.currentPageType].filters; },
|
||||||
set filters(value) { this.pages[this.currentPageType].filters = value; },
|
set filters(value) { this.pages[this.currentPageType].filters = value; },
|
||||||
|
|
||||||
get bulkMode() {
|
get bulkMode() {
|
||||||
const currentType = this.currentPageType;
|
const currentType = this.currentPageType;
|
||||||
if (currentType === MODEL_TYPES.LORA) {
|
if (currentType === MODEL_TYPES.LORA) {
|
||||||
return this.pages.loras.bulkMode;
|
return this.pages.loras.bulkMode;
|
||||||
@@ -224,7 +224,7 @@ export const state = {
|
|||||||
return this.pages[currentType].bulkMode;
|
return this.pages[currentType].bulkMode;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
set bulkMode(value) {
|
set bulkMode(value) {
|
||||||
const currentType = this.currentPageType;
|
const currentType = this.currentPageType;
|
||||||
if (currentType === MODEL_TYPES.LORA) {
|
if (currentType === MODEL_TYPES.LORA) {
|
||||||
this.pages.loras.bulkMode = value;
|
this.pages.loras.bulkMode = value;
|
||||||
@@ -232,11 +232,11 @@ export const state = {
|
|||||||
this.pages[currentType].bulkMode = value;
|
this.pages[currentType].bulkMode = value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get selectedLoras() { return this.pages.loras.selectedLoras; },
|
get selectedLoras() { return this.pages.loras.selectedLoras; },
|
||||||
set selectedLoras(value) { this.pages.loras.selectedLoras = value; },
|
set selectedLoras(value) { this.pages.loras.selectedLoras = value; },
|
||||||
|
|
||||||
get selectedModels() {
|
get selectedModels() {
|
||||||
const currentType = this.currentPageType;
|
const currentType = this.currentPageType;
|
||||||
if (currentType === MODEL_TYPES.LORA) {
|
if (currentType === MODEL_TYPES.LORA) {
|
||||||
return this.pages.loras.selectedLoras;
|
return this.pages.loras.selectedLoras;
|
||||||
@@ -244,7 +244,7 @@ export const state = {
|
|||||||
return this.pages[currentType].selectedModels;
|
return this.pages[currentType].selectedModels;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
set selectedModels(value) {
|
set selectedModels(value) {
|
||||||
const currentType = this.currentPageType;
|
const currentType = this.currentPageType;
|
||||||
if (currentType === MODEL_TYPES.LORA) {
|
if (currentType === MODEL_TYPES.LORA) {
|
||||||
this.pages.loras.selectedLoras = value;
|
this.pages.loras.selectedLoras = value;
|
||||||
@@ -252,10 +252,10 @@ export const state = {
|
|||||||
this.pages[currentType].selectedModels = value;
|
this.pages[currentType].selectedModels = value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get loraMetadataCache() { return this.pages.loras.loraMetadataCache; },
|
get loraMetadataCache() { return this.pages.loras.loraMetadataCache; },
|
||||||
set loraMetadataCache(value) { this.pages.loras.loraMetadataCache = value; },
|
set loraMetadataCache(value) { this.pages.loras.loraMetadataCache = value; },
|
||||||
|
|
||||||
get settings() { return this.global.settings; },
|
get settings() { return this.global.settings; },
|
||||||
set settings(value) { this.global.settings = value; }
|
set settings(value) { this.global.settings = value; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,6 +46,22 @@
|
|||||||
<!-- Recipe controls -->
|
<!-- Recipe controls -->
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
|
<div class="control-group">
|
||||||
|
<select id="sortSelect" title="{{ t('recipes.controls.sort.title') }}">
|
||||||
|
<optgroup label="{{ t('recipes.controls.sort.name') }}">
|
||||||
|
<option value="name:asc">{{ t('recipes.controls.sort.nameAsc') }}</option>
|
||||||
|
<option value="name:desc">{{ t('recipes.controls.sort.nameDesc') }}</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="{{ t('recipes.controls.sort.date') }}">
|
||||||
|
<option value="date:desc">{{ t('recipes.controls.sort.dateDesc') }}</option>
|
||||||
|
<option value="date:asc">{{ t('recipes.controls.sort.dateAsc') }}</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="{{ t('recipes.controls.sort.lorasCount') }}">
|
||||||
|
<option value="loras_count:desc">{{ t('recipes.controls.sort.lorasCountDesc') }}</option>
|
||||||
|
<option value="loras_count:asc">{{ t('recipes.controls.sort.lorasCountAsc') }}</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div title="{{ t('recipes.controls.refresh.title') }}" class="control-group">
|
<div title="{{ t('recipes.controls.refresh.title') }}" class="control-group">
|
||||||
<button onclick="recipeManager.refreshRecipes()"><i class="fas fa-sync"></i> {{ t('common.actions.refresh')
|
<button onclick="recipeManager.refreshRecipes()"><i class="fas fa-sync"></i> {{ t('common.actions.refresh')
|
||||||
}}</button>
|
}}</button>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ describe('RecipeManager', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pageState = {
|
pageState = {
|
||||||
sortBy: 'date',
|
sortBy: 'date:desc',
|
||||||
searchOptions: undefined,
|
searchOptions: undefined,
|
||||||
customFilter: undefined,
|
customFilter: undefined,
|
||||||
duplicatesMode: false,
|
duplicatesMode: false,
|
||||||
@@ -137,8 +137,8 @@ describe('RecipeManager', () => {
|
|||||||
const sortSelectElement = document.createElement('select');
|
const sortSelectElement = document.createElement('select');
|
||||||
sortSelectElement.id = 'sortSelect';
|
sortSelectElement.id = 'sortSelect';
|
||||||
sortSelectElement.innerHTML = `
|
sortSelectElement.innerHTML = `
|
||||||
<option value="date">Date</option>
|
<option value="date:desc">Newest</option>
|
||||||
<option value="name">Name</option>
|
<option value="name:asc">Name A-Z</option>
|
||||||
`;
|
`;
|
||||||
document.body.appendChild(sortSelectElement);
|
document.body.appendChild(sortSelectElement);
|
||||||
|
|
||||||
@@ -183,10 +183,10 @@ describe('RecipeManager', () => {
|
|||||||
expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(1);
|
expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
const sortSelect = document.getElementById('sortSelect');
|
const sortSelect = document.getElementById('sortSelect');
|
||||||
sortSelect.value = 'name';
|
sortSelect.value = 'name:asc';
|
||||||
sortSelect.dispatchEvent(new Event('change', { bubbles: true }));
|
sortSelect.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
|
|
||||||
expect(pageState.sortBy).toBe('name');
|
expect(pageState.sortBy).toBe('name:asc');
|
||||||
expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(2);
|
expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(2);
|
||||||
expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1);
|
expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -601,3 +601,43 @@ async def test_get_paginated_data_filters_by_prompt(recipe_scanner):
|
|||||||
page=1, page_size=10, search="forest", search_options={"prompt": False}
|
page=1, page_size=10, search="forest", search_options={"prompt": False}
|
||||||
)
|
)
|
||||||
assert len(result_disabled["items"]) == 0
|
assert len(result_disabled["items"]) == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_paginated_data_sorting(recipe_scanner):
|
||||||
|
scanner, _ = recipe_scanner
|
||||||
|
|
||||||
|
# Add test recipes
|
||||||
|
# Recipe A: Name "Alpha", Date 10, LoRAs 2
|
||||||
|
await scanner.add_recipe({
|
||||||
|
"id": "A", "title": "Alpha", "created_date": 10.0,
|
||||||
|
"loras": [{}, {}], "file_path": "a.png"
|
||||||
|
})
|
||||||
|
# Recipe B: Name "Beta", Date 20, LoRAs 1
|
||||||
|
await scanner.add_recipe({
|
||||||
|
"id": "B", "title": "Beta", "created_date": 20.0,
|
||||||
|
"loras": [{}], "file_path": "b.png"
|
||||||
|
})
|
||||||
|
# Recipe C: Name "Gamma", Date 5, LoRAs 3
|
||||||
|
await scanner.add_recipe({
|
||||||
|
"id": "C", "title": "Gamma", "created_date": 5.0,
|
||||||
|
"loras": [{}, {}, {}], "file_path": "c.png"
|
||||||
|
})
|
||||||
|
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
|
# Test Name DESC: Gamma, Beta, Alpha
|
||||||
|
res = await scanner.get_paginated_data(page=1, page_size=10, sort_by="name:desc")
|
||||||
|
assert [i["id"] for i in res["items"]] == ["C", "B", "A"]
|
||||||
|
|
||||||
|
# Test LoRA Count DESC: Gamma (3), Alpha (2), Beta (1)
|
||||||
|
res = await scanner.get_paginated_data(page=1, page_size=10, sort_by="loras_count:desc")
|
||||||
|
assert [i["id"] for i in res["items"]] == ["C", "A", "B"]
|
||||||
|
|
||||||
|
# Test LoRA Count ASC: Beta (1), Alpha (2), Gamma (3)
|
||||||
|
res = await scanner.get_paginated_data(page=1, page_size=10, sort_by="loras_count:asc")
|
||||||
|
assert [i["id"] for i in res["items"]] == ["B", "A", "C"]
|
||||||
|
|
||||||
|
# Test Date ASC: Gamma (5), Alpha (10), Beta (20)
|
||||||
|
res = await scanner.get_paginated_data(page=1, page_size=10, sort_by="date:asc")
|
||||||
|
assert [i["id"] for i in res["items"]] == ["C", "A", "B"]
|
||||||
|
|||||||
Reference in New Issue
Block a user