diff --git a/py/routes/api_routes.py b/py/routes/api_routes.py index 13313402..95b224d9 100644 --- a/py/routes/api_routes.py +++ b/py/routes/api_routes.py @@ -667,12 +667,28 @@ class ApiRoutes: """Handle model move request""" try: data = await request.json() - file_path = data.get('file_path') - target_path = data.get('target_path') + file_path = data.get('file_path') # full path of the model file, e.g. /path/to/model.safetensors + target_path = data.get('target_path') # folder path to move the model to, e.g. /path/to/target_folder if not file_path or not target_path: return web.Response(text='File path and target path are required', status=400) + # Check if source and destination are the same + source_dir = os.path.dirname(file_path) + if os.path.normpath(source_dir) == os.path.normpath(target_path): + logger.info(f"Source and target directories are the same: {source_dir}") + return web.json_response({'success': True, 'message': 'Source and target directories are the same'}) + + # Check if target file already exists + file_name = os.path.basename(file_path) + target_file_path = os.path.join(target_path, file_name).replace(os.sep, '/') + + if os.path.exists(target_file_path): + return web.json_response({ + 'success': False, + 'error': f"Target file already exists: {target_file_path}" + }, status=409) # 409 Conflict + # Call scanner to handle the move operation success = await self.scanner.move_model(file_path, target_path) @@ -821,33 +837,55 @@ class ApiRoutes: """Handle bulk model move request""" try: data = await request.json() - file_paths = data.get('file_paths', []) - target_path = data.get('target_path') + file_paths = data.get('file_paths', []) # list of full paths of the model files, e.g. ["/path/to/model1.safetensors", "/path/to/model2.safetensors"] + target_path = data.get('target_path') # folder path to move the models to, e.g. "/path/to/target_folder" if not file_paths or not target_path: return web.Response(text='File paths and target path are required', status=400) results = [] for file_path in file_paths: + # Check if source and destination are the same + source_dir = os.path.dirname(file_path) + if os.path.normpath(source_dir) == os.path.normpath(target_path): + results.append({ + "path": file_path, + "success": True, + "message": "Source and target directories are the same" + }) + continue + + # Check if target file already exists + file_name = os.path.basename(file_path) + target_file_path = os.path.join(target_path, file_name).replace(os.sep, '/') + + if os.path.exists(target_file_path): + results.append({ + "path": file_path, + "success": False, + "message": f"Target file already exists: {target_file_path}" + }) + continue + + # Try to move the model success = await self.scanner.move_model(file_path, target_path) - results.append({"path": file_path, "success": success}) + results.append({ + "path": file_path, + "success": success, + "message": "Success" if success else "Failed to move model" + }) - # Count successes + # Count successes and failures success_count = sum(1 for r in results if r["success"]) + failure_count = len(results) - success_count - if success_count == len(file_paths): - return web.json_response({ - 'success': True, - 'message': f'Successfully moved {success_count} models' - }) - elif success_count > 0: - return web.json_response({ - 'success': True, - 'message': f'Moved {success_count} of {len(file_paths)} models', - 'results': results - }) - else: - return web.Response(text='Failed to move any models', status=500) + return web.json_response({ + 'success': True, + 'message': f'Moved {success_count} of {len(file_paths)} models', + 'results': results, + 'success_count': success_count, + 'failure_count': failure_count + }) except Exception as e: logger.error(f"Error moving models in bulk: {e}", exc_info=True) @@ -962,7 +1000,7 @@ class ApiRoutes: 'base_models': base_models }) except Exception as e: - logger.error(f"Error retrieving base models: {e}", exc_info=True) + logger.error(f"Error retrieving base models: {e}") return web.json_response({ 'success': False, 'error': str(e) diff --git a/static/js/managers/MoveManager.js b/static/js/managers/MoveManager.js index b98eaa59..c2fad001 100644 --- a/static/js/managers/MoveManager.js +++ b/static/js/managers/MoveManager.js @@ -173,11 +173,20 @@ class MoveManager { }) }); + const result = await response.json(); + if (!response.ok) { + if (result && result.error) { + throw new Error(result.error); + } throw new Error('Failed to move model'); } - showToast('Model moved successfully', 'success'); + if (result && result.message) { + showToast(result.message, 'info'); + } else { + showToast('Model moved successfully', 'success'); + } } async moveBulkModels(filePaths, targetPath) { @@ -202,11 +211,44 @@ class MoveManager { }) }); + const result = await response.json(); + if (!response.ok) { throw new Error('Failed to move models'); } - showToast(`Successfully moved ${movedPaths.length} models`, 'success'); + // Display results with more details + if (result.success) { + if (result.failure_count > 0) { + // Some files failed to move + showToast(`Moved ${result.success_count} models, ${result.failure_count} failed`, 'warning'); + + // Log details about failures + console.log('Move operation results:', result.results); + + // Get list of failed files with reasons + const failedFiles = result.results + .filter(r => !r.success) + .map(r => { + const fileName = r.path.substring(r.path.lastIndexOf('/') + 1); + return `${fileName}: ${r.message}`; + }); + + // Show first few failures in a toast + if (failedFiles.length > 0) { + const failureMessage = failedFiles.length <= 3 + ? failedFiles.join('\n') + : failedFiles.slice(0, 3).join('\n') + `\n(and ${failedFiles.length - 3} more)`; + + showToast(`Failed moves:\n${failureMessage}`, 'warning', 6000); + } + } else { + // All files moved successfully + showToast(`Successfully moved ${result.success_count} models`, 'success'); + } + } else { + throw new Error(result.message || 'Failed to move models'); + } } }