From 396924f4cc495980e551a4308b53570843f345f4 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 2 Jun 2025 09:42:28 +0800 Subject: [PATCH] Add badge for duplicate count and update logic in ModelDuplicatesManager and PageControls --- static/css/components/duplicates.css | 41 +++++++++++++ .../js/components/ModelDuplicatesManager.js | 60 +++++++++++++++++++ static/js/components/controls/PageControls.js | 5 ++ templates/components/controls.html | 1 + 4 files changed, 107 insertions(+) diff --git a/static/css/components/duplicates.css b/static/css/components/duplicates.css index 6085db4a..54fd6588 100644 --- a/static/css/components/duplicates.css +++ b/static/css/components/duplicates.css @@ -281,6 +281,47 @@ min-width: 70px; } +/* Badge Styles */ +.badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 16px; /* Reduced from 20px */ + height: 16px; /* Reduced from 20px */ + border-radius: 8px; /* Adjusted for smaller size */ + background-color: var(--lora-error); + color: white; + font-size: 10px; /* Smaller font size */ + font-weight: bold; + padding: 0 4px; /* Reduced padding */ + position: absolute; + top: -8px; /* Moved closer to button */ + right: -8px; /* Moved closer to button */ + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15); /* Softer shadow */ + transition: transform 0.2s ease, opacity 0.2s ease; +} + +.badge:empty { + display: none; +} + +/* Make the pulse animation more subtle */ +.badge.pulse { + animation: badge-pulse 2s infinite; /* Slower animation */ +} + +@keyframes badge-pulse { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.1); /* Less expansion */ + } + 100% { + transform: scale(1); + } +} + /* Responsive adjustments */ @media (max-width: 768px) { .duplicates-banner .banner-content { diff --git a/static/js/components/ModelDuplicatesManager.js b/static/js/components/ModelDuplicatesManager.js index c9652759..6ecfe3e2 100644 --- a/static/js/components/ModelDuplicatesManager.js +++ b/static/js/components/ModelDuplicatesManager.js @@ -14,6 +14,52 @@ export class ModelDuplicatesManager { // Bind methods this.renderModelCard = this.renderModelCard.bind(this); this.renderTooltip = this.renderTooltip.bind(this); + this.checkDuplicatesCount = this.checkDuplicatesCount.bind(this); + + // Check for duplicates on load + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', this.checkDuplicatesCount); + } else { + this.checkDuplicatesCount(); + } + } + + // Method to check for duplicates count using existing endpoint + async checkDuplicatesCount() { + try { + const endpoint = `/api/${this.modelType}/find-duplicates`; + const response = await fetch(endpoint); + + if (!response.ok) { + throw new Error(`Failed to get duplicates count: ${response.statusText}`); + } + + const data = await response.json(); + + if (data.success) { + const duplicatesCount = (data.duplicates || []).length; + this.updateDuplicatesBadge(duplicatesCount); + } else { + this.updateDuplicatesBadge(0); + } + } catch (error) { + console.error('Error checking duplicates count:', error); + this.updateDuplicatesBadge(0); + } + } + + // Method to update the badge + updateDuplicatesBadge(count) { + const badge = document.getElementById('duplicatesBadge'); + if (!badge) return; + + if (count > 0) { + badge.textContent = count; + badge.classList.add('pulse'); + } else { + badge.textContent = ''; + badge.classList.remove('pulse'); + } } async findDuplicates() { @@ -33,6 +79,9 @@ export class ModelDuplicatesManager { this.duplicateGroups = data.duplicates || []; + // Update the badge with the current count + this.updateDuplicatesBadge(this.duplicateGroups.length); + if (this.duplicateGroups.length === 0) { showToast('No duplicate models found', 'info'); return false; @@ -87,6 +136,9 @@ export class ModelDuplicatesManager { const pageState = getCurrentPageState(); pageState.duplicatesMode = false; + // Check duplicates count again to update badge + this.checkDuplicatesCount(); + // 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. @@ -402,6 +454,8 @@ export class ModelDuplicatesManager { // Exit duplicate mode if deletions were successful if (data.total_deleted > 0) { + // Check duplicates count after deletion + this.checkDuplicatesCount(); this.exitDuplicateMode(); } @@ -410,4 +464,10 @@ export class ModelDuplicatesManager { showToast('Failed to delete models: ' + error.message, 'error'); } } + + // Public method to update the badge after refresh + updateDuplicatesBadgeAfterRefresh() { + // Use this method after refresh operations + this.checkDuplicatesCount(); + } } diff --git a/static/js/components/controls/PageControls.js b/static/js/components/controls/PageControls.js index 760612e6..3aab5a4c 100644 --- a/static/js/components/controls/PageControls.js +++ b/static/js/components/controls/PageControls.js @@ -405,6 +405,11 @@ export class PageControls { console.error(`Error ${fullRebuild ? 'rebuilding' : 'refreshing'} ${this.pageType}:`, error); showToast(`Failed to ${fullRebuild ? 'rebuild' : 'refresh'} ${this.pageType}: ${error.message}`, 'error'); } + + if (window.modelDuplicatesManager) { + // Update duplicates badge after refresh + window.modelDuplicatesManager.updateDuplicatesBadgeAfterRefresh(); + } } /** diff --git a/templates/components/controls.html b/templates/components/controls.html index ff1e7492..bc396893 100644 --- a/templates/components/controls.html +++ b/templates/components/controls.html @@ -49,6 +49,7 @@