mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-26 15:38:52 -03:00
Add metadata saving functionality and enhance LoraCard with usage tips and notes
This commit is contained in:
@@ -40,6 +40,7 @@ class ApiRoutes:
|
|||||||
app.router.add_post('/api/download-lora', routes.download_lora)
|
app.router.add_post('/api/download-lora', routes.download_lora)
|
||||||
app.router.add_post('/api/settings', routes.update_settings)
|
app.router.add_post('/api/settings', routes.update_settings)
|
||||||
app.router.add_post('/api/move_model', routes.move_model)
|
app.router.add_post('/api/move_model', routes.move_model)
|
||||||
|
app.router.add_post('/loras/api/save-metadata', routes.save_metadata)
|
||||||
|
|
||||||
async def delete_model(self, request: web.Request) -> web.Response:
|
async def delete_model(self, request: web.Request) -> web.Response:
|
||||||
"""Handle model deletion request"""
|
"""Handle model deletion request"""
|
||||||
@@ -177,6 +178,8 @@ class ApiRoutes:
|
|||||||
"file_path": lora["file_path"].replace(os.sep, "/"),
|
"file_path": lora["file_path"].replace(os.sep, "/"),
|
||||||
"modified": lora["modified"],
|
"modified": lora["modified"],
|
||||||
"from_civitai": lora.get("from_civitai", True),
|
"from_civitai": lora.get("from_civitai", True),
|
||||||
|
"usage_tips": lora.get("usage_tips", ""),
|
||||||
|
"notes": lora.get("notes", ""),
|
||||||
"civitai": self._filter_civitai_data(lora.get("civitai", {}))
|
"civitai": self._filter_civitai_data(lora.get("civitai", {}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,3 +544,40 @@ class ApiRoutes:
|
|||||||
"""Add cleanup method for application shutdown"""
|
"""Add cleanup method for application shutdown"""
|
||||||
if hasattr(cls, '_instance'):
|
if hasattr(cls, '_instance'):
|
||||||
await cls._instance.civitai_client.close()
|
await cls._instance.civitai_client.close()
|
||||||
|
|
||||||
|
async def save_metadata(self, request: web.Request) -> web.Response:
|
||||||
|
"""Handle saving metadata updates"""
|
||||||
|
try:
|
||||||
|
data = await request.json()
|
||||||
|
file_path = data.get('file_path')
|
||||||
|
if not file_path:
|
||||||
|
return web.Response(text='File path is required', status=400)
|
||||||
|
|
||||||
|
# Remove file path from data to avoid saving it
|
||||||
|
metadata_updates = {k: v for k, v in data.items() if k != 'file_path'}
|
||||||
|
|
||||||
|
# Get metadata file path
|
||||||
|
metadata_path = os.path.splitext(file_path)[0] + '.metadata.json'
|
||||||
|
|
||||||
|
# Load existing metadata
|
||||||
|
if os.path.exists(metadata_path):
|
||||||
|
with open(metadata_path, 'r', encoding='utf-8') as f:
|
||||||
|
metadata = json.load(f)
|
||||||
|
else:
|
||||||
|
metadata = {}
|
||||||
|
|
||||||
|
# Update metadata with new values
|
||||||
|
metadata.update(metadata_updates)
|
||||||
|
|
||||||
|
# Save updated metadata
|
||||||
|
with open(metadata_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(metadata, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
# Update cache
|
||||||
|
await self.scanner.update_single_lora_cache(file_path, file_path, metadata)
|
||||||
|
|
||||||
|
return web.json_response({'success': True})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error saving metadata: {e}", exc_info=True)
|
||||||
|
return web.Response(text=str(e), status=500)
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export function createLoraCard(lora) {
|
|||||||
card.dataset.modified = lora.modified;
|
card.dataset.modified = lora.modified;
|
||||||
card.dataset.from_civitai = lora.from_civitai;
|
card.dataset.from_civitai = lora.from_civitai;
|
||||||
card.dataset.base_model = lora.base_model;
|
card.dataset.base_model = lora.base_model;
|
||||||
|
card.dataset.usage_tips = lora.usage_tips;
|
||||||
|
card.dataset.notes = lora.notes;
|
||||||
card.dataset.meta = JSON.stringify(lora.civitai || {});
|
card.dataset.meta = JSON.stringify(lora.civitai || {});
|
||||||
|
|
||||||
const version = state.previewVersions.get(lora.file_path);
|
const version = state.previewVersions.get(lora.file_path);
|
||||||
@@ -61,13 +63,15 @@ export function createLoraCard(lora) {
|
|||||||
card.addEventListener('click', () => {
|
card.addEventListener('click', () => {
|
||||||
const loraMeta = {
|
const loraMeta = {
|
||||||
sha256: card.dataset.sha256,
|
sha256: card.dataset.sha256,
|
||||||
file_path: card.dataset.filepath.replace(/[^/]+$/, ''), // Extract directory path
|
file_path: card.dataset.filepath,
|
||||||
model_name: card.dataset.name,
|
model_name: card.dataset.name,
|
||||||
file_name: card.dataset.file_name,
|
file_name: card.dataset.file_name,
|
||||||
folder: card.dataset.folder,
|
folder: card.dataset.folder,
|
||||||
modified: card.dataset.modified,
|
modified: card.dataset.modified,
|
||||||
from_civitai: card.dataset.from_civitai === 'true',
|
from_civitai: card.dataset.from_civitai === 'true',
|
||||||
base_model: card.dataset.base_model,
|
base_model: card.dataset.base_model,
|
||||||
|
usage_tips: card.dataset.usage_tips,
|
||||||
|
notes: card.dataset.notes,
|
||||||
civitai: JSON.parse(card.dataset.meta || '{}')
|
civitai: JSON.parse(card.dataset.meta || '{}')
|
||||||
};
|
};
|
||||||
showLoraModal(loraMeta);
|
showLoraModal(loraMeta);
|
||||||
@@ -105,8 +109,8 @@ export function createLoraCard(lora) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function showLoraModal(lora) {
|
export function showLoraModal(lora) {
|
||||||
const escapedWords = lora.trainedWords?.length ?
|
const escapedWords = lora.civitai?.trainedWords?.length ?
|
||||||
lora.trainedWords.map(word => word.replace(/'/g, '\\\'')) : [];
|
lora.civitai.trainedWords.map(word => word.replace(/'/g, '\\\'')) : [];
|
||||||
|
|
||||||
const content = `
|
const content = `
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@@ -128,7 +132,7 @@ export function showLoraModal(lora) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<label>Location</label>
|
<label>Location</label>
|
||||||
<span class="file-path">${lora.file_path || 'N/A'}</span>
|
<span class="file-path">${lora.file_path.replace(/[^/]+$/, '') || 'N/A'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<label>Base Model</label>
|
<label>Base Model</label>
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ async def get_file_info(file_path: str) -> LoraMetadata:
|
|||||||
modified=os.path.getmtime(file_path),
|
modified=os.path.getmtime(file_path),
|
||||||
sha256=await calculate_sha256(file_path),
|
sha256=await calculate_sha256(file_path),
|
||||||
base_model="Unknown", # Will be updated later
|
base_model="Unknown", # Will be updated later
|
||||||
|
usage_tips="",
|
||||||
|
notes="",
|
||||||
from_civitai=True,
|
from_civitai=True,
|
||||||
preview_url=normalize_path(preview_url),
|
preview_url=normalize_path(preview_url),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class LoraMetadata:
|
|||||||
sha256: str # SHA256 hash of the file
|
sha256: str # SHA256 hash of the file
|
||||||
base_model: str # Base model (SD1.5/SD2.1/SDXL/etc.)
|
base_model: str # Base model (SD1.5/SD2.1/SDXL/etc.)
|
||||||
preview_url: str # Preview image URL
|
preview_url: str # Preview image URL
|
||||||
|
usage_tips: str = "" # Usage tips for the model
|
||||||
|
notes: str = "" # Additional notes
|
||||||
from_civitai: bool = True # Whether the lora is from Civitai
|
from_civitai: bool = True # Whether the lora is from Civitai
|
||||||
civitai: Optional[Dict] = None # Civitai API data if available
|
civitai: Optional[Dict] = None # Civitai API data if available
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user