Add bulk delete endpoint for checkpoints and enhance ModelDuplicatesManager for better handling of model types

This commit is contained in:
Will Miao
2025-06-02 08:54:31 +08:00
parent 26f9779fbf
commit 7545312229
5 changed files with 41 additions and 7 deletions

View File

@@ -62,6 +62,9 @@ class CheckpointsRoutes:
app.router.add_get('/api/checkpoints/find-duplicates', self.find_duplicate_checkpoints)
app.router.add_get('/api/checkpoints/find-filename-conflicts', self.find_filename_conflicts)
# Add new endpoint for bulk deleting checkpoints
app.router.add_post('/api/checkpoints/bulk-delete', self.bulk_delete_checkpoints)
async def get_checkpoints(self, request):
"""Get paginated checkpoint data"""
try:
@@ -793,3 +796,18 @@ class CheckpointsRoutes:
"success": False,
"error": str(e)
}, status=500)
async def bulk_delete_checkpoints(self, request: web.Request) -> web.Response:
"""Handle bulk deletion of checkpoint models"""
try:
if self.scanner is None:
self.scanner = await ServiceRegistry.get_checkpoint_scanner()
return await ModelRouteUtils.handle_bulk_delete_models(request, self.scanner)
except Exception as e:
logger.error(f"Error in bulk delete checkpoints: {e}", exc_info=True)
return web.json_response({
'success': False,
'error': str(e)
}, status=500)

View File

@@ -133,7 +133,7 @@ class ModelScanner:
os.rename(temp_path, cache_path)
logger.info(f"Saved {self.model_type} cache with {len(self._cache.raw_data)} models to {cache_path}")
logger.info(f"Hash index stats - hash_to_path: {len(self._hash_index._hash_to_path)}, filename_to_hash: {len(self._hash_index._filename_to_hash)}, duplicate_hashes: {len(self._hash_index._duplicate_hashes)}, duplicate_filenames: {len(self._hash_index._duplicate_filenames)}")
logger.debug(f"Hash index stats - hash_to_path: {len(self._hash_index._hash_to_path)}, filename_to_hash: {len(self._hash_index._filename_to_hash)}, duplicate_hashes: {len(self._hash_index._duplicate_hashes)}, duplicate_filenames: {len(self._hash_index._duplicate_filenames)}")
return True
except Exception as e:
logger.error(f"Error saving {self.model_type} cache to disk: {e}")

View File

@@ -16,7 +16,7 @@ class CheckpointsPageManager {
window.checkpointDownloadManager = new CheckpointDownloadManager();
// Initialize the ModelDuplicatesManager
this.duplicatesManager = new ModelDuplicatesManager(this);
this.duplicatesManager = new ModelDuplicatesManager(this, 'checkpoints');
// Expose only necessary functions to global scope
this._exposeRequiredGlobalFunctions();

View File

@@ -1,16 +1,15 @@
// Model Duplicates Manager Component for LoRAs and Checkpoints
import { showToast } from '../utils/uiHelpers.js';
import { state, getCurrentPageState } from '../state/index.js';
import { initializeInfiniteScroll } from '../utils/infiniteScroll.js';
import { formatDate } from '../utils/formatters.js';
export class ModelDuplicatesManager {
constructor(pageManager) {
constructor(pageManager, modelType = 'loras') {
this.pageManager = pageManager;
this.duplicateGroups = [];
this.inDuplicateMode = false;
this.selectedForDeletion = new Set();
this.modelType = 'loras'; // Default to loras, could be 'checkpoints'
this.modelType = modelType; // Use the provided modelType or default to 'loras'
// Bind methods
this.renderModelCard = this.renderModelCard.bind(this);
@@ -91,11 +90,11 @@ export class ModelDuplicatesManager {
// Instead of trying to restore the virtual scroller,
// simply redirect to reload the page
// TODO: While this is a workaround rather than a deep fix, it's a pragmatic solution that will immediately resolve the issue for users. We can investigate the underlying cause more thoroughly later when there's time for more extensive debugging.
window.location.href = '/loras';
window.location.href = `/${this.modelType}`;
}
renderDuplicateGroups() {
const modelGrid = document.getElementById('loraGrid');
const modelGrid = document.getElementById(this.modelType === 'loras' ? 'loraGrid' : 'checkpointGrid');
if (!modelGrid) return;
// Clear existing content

View File

@@ -31,6 +31,23 @@
{% block content %}
{% include 'components/controls.html' %}
<!-- Duplicates banner (hidden by default) -->
<div id="duplicatesBanner" class="duplicates-banner" style="display: none;">
<div class="banner-content">
<i class="fas fa-exclamation-triangle"></i>
<span id="duplicatesCount">Found 0 duplicate groups</span>
<div class="banner-actions">
<button class="btn-delete-selected disabled" onclick="modelDuplicatesManager.deleteSelectedDuplicates()">
Delete Selected (<span id="duplicatesSelectedCount">0</span>)
</button>
<button class="btn-exit" onclick="modelDuplicatesManager.exitDuplicateMode()">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</div>
<!-- Checkpoint cards container -->
<div class="card-grid" id="checkpointGrid">
<!-- Cards will be dynamically inserted here -->