mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
feat(localization): enhance toast messages for recipes and example images with improved error handling and success feedback
This commit is contained in:
@@ -89,7 +89,7 @@ export async function fetchRecipesPage(page = 1, pageSize = 100) {
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching recipes:', error);
|
||||
showToast(`Failed to fetch recipes: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.fetchFailed', { message: error.message }, 'error');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ export async function resetAndReloadWithVirtualScroll(options = {}) {
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`Error reloading ${modelType}s:`, error);
|
||||
showToast(`Failed to reload ${modelType}s: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.reloadFailed', { modelType: modelType, message: error.message }, 'error');
|
||||
throw error;
|
||||
} finally {
|
||||
pageState.isLoading = false;
|
||||
@@ -179,7 +179,7 @@ export async function loadMoreWithVirtualScroll(options = {}) {
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`Error loading ${modelType}s:`, error);
|
||||
showToast(`Failed to load ${modelType}s: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.loadFailed', { modelType: modelType, message: error.message }, 'error');
|
||||
throw error;
|
||||
} finally {
|
||||
pageState.isLoading = false;
|
||||
@@ -217,10 +217,10 @@ export async function refreshRecipes() {
|
||||
// After successful cache rebuild, reload the recipes
|
||||
await resetAndReload();
|
||||
|
||||
showToast('Refresh complete', 'success');
|
||||
showToast('toast.recipes.refreshComplete', {}, 'success');
|
||||
} catch (error) {
|
||||
console.error('Error refreshing recipes:', error);
|
||||
showToast(error.message || 'Failed to refresh recipes', 'error');
|
||||
showToast('toast.recipes.refreshFailed', { message: error.message }, 'error');
|
||||
} finally {
|
||||
state.loadingManager.hide();
|
||||
state.loadingManager.restoreProgressBar();
|
||||
@@ -285,7 +285,7 @@ export async function updateRecipeMetadata(filePath, updates) {
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
showToast(`Failed to update recipe: ${data.error}`, 'error');
|
||||
showToast('toast.recipes.updateFailed', { error: data.error }, 'error');
|
||||
throw new Error(data.error || 'Failed to update recipe');
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ export async function updateRecipeMetadata(filePath, updates) {
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error updating recipe:', error);
|
||||
showToast(`Error updating recipe: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.updateError', { message: error.message }, 'error');
|
||||
throw error;
|
||||
} finally {
|
||||
state.loadingManager.hide();
|
||||
|
||||
@@ -199,7 +199,7 @@ class RecipeCard {
|
||||
// Get recipe ID
|
||||
const recipeId = this.recipe.id;
|
||||
if (!recipeId) {
|
||||
showToast('Cannot send recipe: Missing recipe ID', 'error');
|
||||
showToast('toast.recipes.cannotSend', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,11 +214,11 @@ class RecipeCard {
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to send recipe to workflow: ', err);
|
||||
showToast('Failed to send recipe to workflow', 'error');
|
||||
showToast('toast.recipes.sendFailed', {}, 'error');
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error sending recipe to workflow:', error);
|
||||
showToast('Error sending recipe to workflow', 'error');
|
||||
showToast('toast.recipes.sendError', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ class RecipeCard {
|
||||
const recipeId = this.recipe.id;
|
||||
const filePath = this.recipe.file_path;
|
||||
if (!recipeId) {
|
||||
showToast('Cannot delete recipe: Missing recipe ID', 'error');
|
||||
showToast('toast.recipes.cannotDelete', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ class RecipeCard {
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error showing delete confirmation:', error);
|
||||
showToast('Error showing delete confirmation', 'error');
|
||||
showToast('toast.recipes.deleteConfirmationError', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ class RecipeCard {
|
||||
const recipeId = deleteModal.dataset.recipeId;
|
||||
|
||||
if (!recipeId) {
|
||||
showToast('Cannot delete recipe: Missing recipe ID', 'error');
|
||||
showToast('toast.recipes.cannotDelete', {}, 'error');
|
||||
modalManager.closeModal('deleteModal');
|
||||
return;
|
||||
}
|
||||
@@ -312,7 +312,7 @@ class RecipeCard {
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
showToast('Recipe deleted successfully', 'success');
|
||||
showToast('toast.recipes.deletedSuccessfully', {}, 'success');
|
||||
|
||||
state.virtualScroller.removeItemByFilePath(deleteModal.dataset.filePath);
|
||||
|
||||
@@ -320,7 +320,7 @@ class RecipeCard {
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error deleting recipe:', error);
|
||||
showToast('Error deleting recipe: ' + error.message, 'error');
|
||||
showToast('toast.recipes.deleteFailed', { message: error.message }, 'error');
|
||||
|
||||
// Reset button state
|
||||
deleteBtn.textContent = originalText;
|
||||
@@ -333,12 +333,12 @@ class RecipeCard {
|
||||
// Get recipe ID
|
||||
const recipeId = this.recipe.id;
|
||||
if (!recipeId) {
|
||||
showToast('Cannot share recipe: Missing recipe ID', 'error');
|
||||
showToast('toast.recipes.cannotShare', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading toast
|
||||
showToast('Preparing recipe for sharing...', 'info');
|
||||
showToast('toast.recipes.preparingForSharing', {}, 'info');
|
||||
|
||||
// Call the API to process the image with metadata
|
||||
fetch(`/api/recipe/${recipeId}/share`)
|
||||
@@ -363,15 +363,15 @@ class RecipeCard {
|
||||
downloadLink.click();
|
||||
document.body.removeChild(downloadLink);
|
||||
|
||||
showToast('Recipe download started', 'success');
|
||||
showToast('toast.recipes.downloadStarted', {}, 'success');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error sharing recipe:', error);
|
||||
showToast('Error sharing recipe: ' + error.message, 'error');
|
||||
showToast('toast.recipes.shareError', { message: error.message }, 'error');
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error sharing recipe:', error);
|
||||
showToast('Error preparing recipe for sharing', 'error');
|
||||
showToast('toast.recipes.sharePreparationError', {}, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ class RecipeModal {
|
||||
updateRecipeMetadata(this.filePath, { title: newTitle })
|
||||
.then(data => {
|
||||
// Show success toast
|
||||
showToast('Recipe name updated successfully', 'success');
|
||||
showToast('toast.recipes.nameUpdated', {}, 'success');
|
||||
|
||||
// Update the current recipe object
|
||||
this.currentRecipe.title = newTitle;
|
||||
@@ -596,7 +596,7 @@ class RecipeModal {
|
||||
updateRecipeMetadata(this.filePath, { tags: newTags })
|
||||
.then(data => {
|
||||
// Show success toast
|
||||
showToast('Recipe tags updated successfully', 'success');
|
||||
showToast('toast.recipes.tagsUpdated', {}, 'success');
|
||||
|
||||
// Update the current recipe object
|
||||
this.currentRecipe.tags = newTags;
|
||||
@@ -717,7 +717,7 @@ class RecipeModal {
|
||||
updateRecipeMetadata(this.filePath, { source_path: newSourceUrl })
|
||||
.then(data => {
|
||||
// Show success toast
|
||||
showToast('Source URL updated successfully', 'success');
|
||||
showToast('toast.recipes.sourceUrlUpdated', {}, 'success');
|
||||
|
||||
// Update source URL in the UI
|
||||
sourceUrlText.textContent = newSourceUrl || 'No source URL';
|
||||
@@ -778,7 +778,7 @@ class RecipeModal {
|
||||
// Fetch recipe syntax from backend and copy to clipboard
|
||||
async fetchAndCopyRecipeSyntax() {
|
||||
if (!this.recipeId) {
|
||||
showToast('No recipe ID available', 'error');
|
||||
showToast('toast.recipes.noRecipeId', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -800,7 +800,7 @@ class RecipeModal {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching recipe syntax:', error);
|
||||
showToast(`Error copying recipe syntax: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.copyFailed', { message: error.message }, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -817,7 +817,7 @@ class RecipeModal {
|
||||
console.log("missingLoras", missingLoras);
|
||||
|
||||
if (missingLoras.length === 0) {
|
||||
showToast('No missing LoRAs to download', 'info');
|
||||
showToast('toast.recipes.noMissingLoras', {}, 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -856,7 +856,7 @@ class RecipeModal {
|
||||
const validLoras = lorasWithVersionInfo.filter(lora => lora !== null);
|
||||
|
||||
if (validLoras.length === 0) {
|
||||
showToast('Failed to get information for missing LoRAs', 'error');
|
||||
showToast('toast.recipes.missingLorasInfoFailed', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -902,7 +902,7 @@ class RecipeModal {
|
||||
window.importManager.downloadMissingLoras(recipeData, this.currentRecipe.id);
|
||||
} catch (error) {
|
||||
console.error("Error downloading missing LoRAs:", error);
|
||||
showToast('Error preparing LoRAs for download', 'error');
|
||||
showToast('toast.recipes.preparingForDownloadFailed', {}, 'error');
|
||||
} finally {
|
||||
state.loadingManager.hide();
|
||||
}
|
||||
@@ -988,7 +988,7 @@ class RecipeModal {
|
||||
|
||||
async reconnectLora(loraIndex, inputValue) {
|
||||
if (!inputValue || !inputValue.trim()) {
|
||||
showToast('Please enter a LoRA name or syntax', 'error');
|
||||
showToast('toast.recipes.enterLoraName', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1026,7 @@ class RecipeModal {
|
||||
this.currentRecipe.loras[loraIndex] = result.updated_lora;
|
||||
|
||||
// Show success message
|
||||
showToast('LoRA reconnected successfully', 'success');
|
||||
showToast('toast.recipes.reconnectedSuccessfully', {}, 'success');
|
||||
|
||||
// Refresh modal to show updated content
|
||||
setTimeout(() => {
|
||||
@@ -1037,11 +1037,11 @@ class RecipeModal {
|
||||
loras: this.currentRecipe.loras
|
||||
});
|
||||
} else {
|
||||
showToast(`Error: ${result.error}`, 'error');
|
||||
showToast('toast.recipes.reconnectFailed', { message: result.error }, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error reconnecting LoRA:', error);
|
||||
showToast(`Error reconnecting LoRA: ${error.message}`, 'error');
|
||||
showToast('toast.recipes.reconnectFailed', { message: error.message }, 'error');
|
||||
} finally {
|
||||
state.loadingManager.hide();
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ export function initMetadataPanelHandlers(container) {
|
||||
await copyToClipboard(promptElement.textContent, 'Prompt copied to clipboard');
|
||||
} catch (err) {
|
||||
console.error('Copy failed:', err);
|
||||
showToast('Copy failed', 'error');
|
||||
showToast('toast.triggerWords.copyFailed', {}, 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -432,7 +432,7 @@ export function initMediaControlHandlers(container) {
|
||||
}, 600);
|
||||
|
||||
// Show success toast
|
||||
showToast('Example image deleted', 'success');
|
||||
showToast('toast.exampleImages.deleted', {}, 'success');
|
||||
|
||||
// Create an update object with only the necessary properties
|
||||
const updateData = {
|
||||
@@ -456,7 +456,7 @@ export function initMediaControlHandlers(container) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error deleting example image:', error);
|
||||
showToast('Failed to delete example image', 'error');
|
||||
showToast('toast.exampleImages.deleteFailed', {}, 'error');
|
||||
|
||||
// Reset button state
|
||||
this.disabled = false;
|
||||
@@ -536,7 +536,7 @@ function initSetPreviewHandlers(container) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting preview:', error);
|
||||
showToast('Failed to set preview image', 'error');
|
||||
showToast('toast.exampleImages.setPreviewFailed', {}, 'error');
|
||||
} finally {
|
||||
// Restore button state
|
||||
this.innerHTML = '<i class="fas fa-image"></i>';
|
||||
|
||||
@@ -412,7 +412,7 @@ async function handleImportFiles(files, modelHash, importContainer) {
|
||||
// Initialize the import UI for the new content
|
||||
initExampleImport(modelHash, showcaseTab);
|
||||
|
||||
showToast('Example images imported successfully', 'success');
|
||||
showToast('toast.import.imagesImported', {}, 'success');
|
||||
|
||||
// Update VirtualScroller if available
|
||||
if (state.virtualScroller && result.model_file_path) {
|
||||
|
||||
@@ -283,13 +283,13 @@ export class DownloadManager {
|
||||
|
||||
async proceedToLocation() {
|
||||
if (!this.currentVersion) {
|
||||
showToast('Please select a version', 'error');
|
||||
showToast('toast.loras.pleaseSelectVersion', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const existsLocally = this.currentVersion.existsLocally;
|
||||
if (existsLocally) {
|
||||
showToast('This version already exists in your library', 'info');
|
||||
showToast('toast.loras.versionExists', {}, 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ export class DownloadManager {
|
||||
downloadId
|
||||
);
|
||||
|
||||
showToast('Download completed successfully', 'success');
|
||||
showToast('toast.loras.downloadCompleted', {}, 'success');
|
||||
modalManager.closeModal('downloadModal');
|
||||
|
||||
ws.close();
|
||||
@@ -523,11 +523,11 @@ export class DownloadManager {
|
||||
await this.folderTreeManager.loadTree(treeData.tree);
|
||||
} else {
|
||||
console.error('Failed to fetch folder tree:', treeData.error);
|
||||
showToast('Failed to load folder tree', 'error');
|
||||
showToast('toast.import.folderTreeFailed', {}, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing folder tree:', error);
|
||||
showToast('Error loading folder tree', 'error');
|
||||
showToast('toast.import.folderTreeError', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ class ExampleImagesManager {
|
||||
if (!data.success) {
|
||||
console.error('Failed to update example images path in backend:', data.error);
|
||||
} else {
|
||||
showToast('Example images path updated successfully', 'success');
|
||||
showToast('toast.exampleImages.pathUpdated', {}, 'success');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to update example images path:', error);
|
||||
@@ -187,7 +187,7 @@ class ExampleImagesManager {
|
||||
this.startDownload();
|
||||
} else {
|
||||
// If download is in progress, show info toast
|
||||
showToast('Download already in progress', 'info');
|
||||
showToast('toast.exampleImages.downloadInProgress', {}, 'info');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ class ExampleImagesManager {
|
||||
|
||||
async startDownload() {
|
||||
if (this.isDownloading) {
|
||||
showToast('Download already in progress', 'warning');
|
||||
showToast('toast.exampleImages.downloadInProgress', {}, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ class ExampleImagesManager {
|
||||
const outputDir = document.getElementById('exampleImagesPath').value || '';
|
||||
|
||||
if (!outputDir) {
|
||||
showToast('Please enter a download location first', 'warning');
|
||||
showToast('toast.exampleImages.enterLocationFirst', {}, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ class ExampleImagesManager {
|
||||
this.showProgressPanel();
|
||||
this.startProgressUpdates();
|
||||
this.updateDownloadButtonText();
|
||||
showToast('Example images download started', 'success');
|
||||
showToast('toast.exampleImages.downloadStarted', {}, 'success');
|
||||
|
||||
// Close settings modal
|
||||
modalManager.closeModal('settingsModal');
|
||||
@@ -289,7 +289,7 @@ class ExampleImagesManager {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to start download:', error);
|
||||
showToast('Failed to start download', 'error');
|
||||
showToast('toast.exampleImages.downloadStartFailed', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,13 +319,13 @@ class ExampleImagesManager {
|
||||
}
|
||||
|
||||
this.updateDownloadButtonText();
|
||||
showToast('Download paused', 'info');
|
||||
showToast('toast.exampleImages.downloadPaused', {}, 'info');
|
||||
} else {
|
||||
showToast(data.error || 'Failed to pause download', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to pause download:', error);
|
||||
showToast('Failed to pause download', 'error');
|
||||
showToast('toast.exampleImages.pauseFailed', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,13 +355,13 @@ class ExampleImagesManager {
|
||||
}
|
||||
|
||||
this.updateDownloadButtonText();
|
||||
showToast('Download resumed', 'success');
|
||||
showToast('toast.exampleImages.downloadResumed', {}, 'success');
|
||||
} else {
|
||||
showToast(data.error || 'Failed to resume download', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to resume download:', error);
|
||||
showToast('Failed to resume download', 'error');
|
||||
showToast('toast.exampleImages.resumeFailed', {}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ export class FilterManager {
|
||||
} else {
|
||||
this.filterButton.classList.remove('active');
|
||||
if (showToastNotification) {
|
||||
showToast('Filters cleared', 'info');
|
||||
showToast('toast.filters.cleared', {}, 'info');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class DownloadManager {
|
||||
const isDownloadOnly = !!this.importManager.recipeId;
|
||||
|
||||
if (!isDownloadOnly && !this.importManager.recipeName) {
|
||||
showToast('Please enter a recipe name', 'error');
|
||||
showToast('toast.import.enterRecipeName', {}, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ export class DownloadManager {
|
||||
// Show success message
|
||||
if (isDownloadOnly) {
|
||||
if (failedDownloads === 0) {
|
||||
showToast('LoRAs downloaded successfully', 'success');
|
||||
showToast('toast.loras.downloadSuccessful', {}, 'success');
|
||||
}
|
||||
} else {
|
||||
showToast(`Recipe "${this.importManager.recipeName}" saved successfully`, 'success');
|
||||
showToast('toast.recipes.nameSaved', { name: this.importManager.recipeName }, 'success');
|
||||
}
|
||||
|
||||
// Close modal
|
||||
@@ -238,15 +238,19 @@ export class DownloadManager {
|
||||
|
||||
// Show appropriate completion message based on results
|
||||
if (failedDownloads === 0) {
|
||||
showToast(`All ${completedDownloads} LoRAs downloaded successfully`, 'success');
|
||||
showToast('toast.loras.allDownloadSuccessful', { count: completedDownloads }, 'success');
|
||||
} else {
|
||||
if (accessFailures > 0) {
|
||||
showToast(
|
||||
`Downloaded ${completedDownloads} of ${this.importManager.downloadableLoRAs.length} LoRAs. ${accessFailures} failed due to access restrictions. Check your API key in settings or early access status.`,
|
||||
'error'
|
||||
);
|
||||
showToast('toast.loras.downloadPartialWithAccess', {
|
||||
completed: completedDownloads,
|
||||
total: this.importManager.downloadableLoRAs.length,
|
||||
accessFailures: accessFailures
|
||||
}, 'error');
|
||||
} else {
|
||||
showToast(`Downloaded ${completedDownloads} of ${this.importManager.downloadableLoRAs.length} LoRAs`, 'error');
|
||||
showToast('toast.loras.downloadPartialSuccess', {
|
||||
completed: completedDownloads,
|
||||
total: this.importManager.downloadableLoRAs.length
|
||||
}, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user