From e33da502785caab49d08c3c4f9a402675fd2997e Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 8 May 2025 18:33:19 +0800 Subject: [PATCH] refactor: update duplicate recipe management; simplify UI and remove deprecated functions --- static/css/components/import-modal.css | 173 +++++++-------- static/js/managers/ImportManager.js | 42 +--- .../js/managers/import/RecipeDataManager.js | 202 ++++-------------- templates/components/import_modal.html | 10 +- 4 files changed, 128 insertions(+), 299 deletions(-) diff --git a/static/css/components/import-modal.css b/static/css/components/import-modal.css index 112c5d60..86bbf33a 100644 --- a/static/css/components/import-modal.css +++ b/static/css/components/import-modal.css @@ -291,7 +291,7 @@ gap: 8px; padding: var(--space-1); border: 1px solid var(--border-color); - border-radius: var(--border-radius-sm); + border-radius: var (--border-radius-sm); background: var(--lora-surface); } @@ -752,14 +752,14 @@ align-items: flex-start; gap: 12px; padding: 12px 16px; - background: oklch(var(--lora-accent) / 0.1); - border: 1px solid var(--lora-accent); + background: oklch(var(--lora-warning) / 0.1); + border: 1px solid var(--lora-warning); border-radius: var(--border-radius-sm) var(--border-radius-sm) 0 0; color: var(--text-color); } .duplicate-warning .warning-icon { - color: var(--lora-accent); + color: var(--lora-warning); font-size: 1.2em; padding-top: 2px; } @@ -776,59 +776,67 @@ .duplicate-warning .warning-text { font-size: 0.9em; line-height: 1.4; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 8px; +} + +.toggle-duplicates-btn { + background: none; + border: none; + color: var(--lora-warning); + cursor: pointer; + font-size: 0.9em; + display: flex; + align-items: center; + gap: 6px; + padding: 4px 8px; + border-radius: var(--border-radius-xs); +} + +.toggle-duplicates-btn:hover { + background: oklch(var(--lora-warning) / 0.1); } .duplicate-recipes-list { - max-height: 250px; - overflow-y: auto; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 12px; + padding: 16px; border: 1px solid var(--border-color); border-top: none; border-radius: 0 0 var(--border-radius-sm) var(--border-radius-sm); background: var(--bg-color); + max-height: 300px; + overflow-y: auto; + transition: max-height 0.3s ease, padding 0.3s ease; } -.duplicate-recipe-item { - display: flex; - gap: var(--space-2); - padding: var(--space-2); - border-bottom: 1px solid var(--border-color); +.duplicate-recipes-list.collapsed { + max-height: 0; + padding: 0 16px; + overflow: hidden; +} + +.duplicate-recipe-card { position: relative; - transition: background-color 0.2s; + border-radius: var(--border-radius-sm); + overflow: hidden; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: transform 0.2s ease; } -.duplicate-recipe-item:last-child { - border-bottom: none; -} - -.duplicate-recipe-item:hover { - background: var(--lora-surface); -} - -.duplicate-recipe-item.marked-for-deletion { - background: rgba(var(--lora-error-rgb), 0.1); - opacity: 0.8; -} - -.duplicate-recipe-item.marked-for-deletion::before { - content: 'Will be deleted'; - position: absolute; - right: 10px; - top: 5px; - background: var(--lora-error); - color: white; - padding: 2px 8px; - border-radius: var(--border-radius-xs); - font-size: 0.8em; +.duplicate-recipe-card:hover { + transform: translateY(-2px); } .duplicate-recipe-preview { - width: 80px; - height: 80px; - flex-shrink: 0; - border-radius: var(--border-radius-xs); - overflow: hidden; + width: 100%; + position: relative; + aspect-ratio: 2/3; background: var(--bg-color); - border: 1px solid var(--border-color); } .duplicate-recipe-preview img { @@ -837,18 +845,17 @@ object-fit: cover; } -.duplicate-recipe-content { - display: flex; - flex-direction: column; - gap: 8px; - flex: 1; - min-width: 0; -} - .duplicate-recipe-title { - font-weight: 500; - font-size: 1em; - margin-bottom: 4px; + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 8px; + background: rgba(0, 0, 0, 0.7); + color: white; + font-size: 0.85em; + line-height: 1.3; + max-height: 50%; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; @@ -856,67 +863,31 @@ -webkit-box-orient: vertical; } -.duplicate-recipe-info { +.duplicate-recipe-details { + padding: 8px; + background: var(--bg-color); + font-size: 0.75em; display: flex; - gap: 12px; - font-size: 0.85em; + justify-content: space-between; + align-items: center; color: var(--text-color); opacity: 0.8; } -.duplicate-recipe-date, +.duplicate-recipe-date, .duplicate-recipe-lora-count { display: flex; align-items: center; gap: 4px; } -.duplicate-recipe-actions { - display: flex; - justify-content: center; - align-items: center; - min-width: 80px; -} - -.duplicate-recipe-actions button { - padding: 6px 12px; - font-size: 0.85em; - display: flex; - align-items: center; - gap: 4px; - white-space: nowrap; - width: 100%; - justify-content: center; -} - -.danger-btn { - background: var(--lora-error) !important; - color: white !important; - border: none !important; -} - -.danger-btn:hover { - background: oklch(from var(--lora-error) l c h / 0.9) !important; -} - +/* Remove the old duplicate styles that are no longer needed */ +.duplicate-recipe-item, +.duplicate-recipe-content, +.duplicate-recipe-actions, +.danger-btn, .view-recipe-btn { - background: var(--lora-surface) !important; - color: var(--text-color) !important; - border: 1px solid var(--border-color) !important; -} - -.view-recipe-btn:hover { - background: var(--lora-accent) !important; - color: var(--lora-text) !important; -} - -.warning-btn { - background: var(--lora-warning) !important; - color: white !important; -} - -.warning-btn:hover { - background: oklch(from var(--lora-warning) l c h / 0.9) !important; + /* These styles are being replaced by the card layout */ } /* Modal buttons layout to accommodate multiple buttons */ diff --git a/static/js/managers/ImportManager.js b/static/js/managers/ImportManager.js index 5e3d80d0..831ae148 100644 --- a/static/js/managers/ImportManager.js +++ b/static/js/managers/ImportManager.js @@ -120,6 +120,9 @@ export class ImportManager { const earlyAccessWarning = document.getElementById('earlyAccessWarning'); if (earlyAccessWarning) earlyAccessWarning.remove(); + + // Reset duplicate related properties + this.duplicateRecipes = []; } toggleImportMode(mode) { @@ -246,44 +249,21 @@ export class ImportManager { } /** - * Marks or unmarks a duplicate recipe for deletion - * @param {string} recipeId - The ID of the recipe to mark/unmark - * @param {HTMLElement} buttonElement - The button element that was clicked + * NOTE: This function is no longer needed with the simplified duplicates flow. + * We're keeping it as a no-op stub to avoid breaking existing code that might call it. */ markDuplicateForDeletion(recipeId, buttonElement) { - // Initialize recipesToDelete array if it doesn't exist - if (!this.recipesToDelete) { - this.recipesToDelete = []; - } - - // Get the recipe item container - const recipeItem = buttonElement.closest('.duplicate-recipe-item'); - if (!recipeItem) return; - - // Check if this recipe is already marked for deletion - const isMarked = this.recipesToDelete.includes(recipeId); - - if (isMarked) { - // Unmark the recipe - this.recipesToDelete = this.recipesToDelete.filter(id => id !== recipeId); - recipeItem.classList.remove('marked-for-deletion'); - buttonElement.innerHTML = ' Delete'; - } else { - // Mark the recipe for deletion - this.recipesToDelete.push(recipeId); - recipeItem.classList.add('marked-for-deletion'); - buttonElement.innerHTML = ' Keep'; - } + // This functionality has been removed + console.log('markDuplicateForDeletion is deprecated'); } /** - * Imports the recipe as new, ignoring duplicates + * NOTE: This function is no longer needed with the simplified duplicates flow. + * We're keeping it as a no-op stub to avoid breaking existing code that might call it. */ importRecipeAnyway() { - // Set flag to indicate we're importing as a new recipe - this.importAsNew = true; - - // Proceed with normal flow but skip duplicate replacement + // This functionality has been simplified + // Just proceed with normal flow this.proceedFromDetails(); } diff --git a/static/js/managers/import/RecipeDataManager.js b/static/js/managers/import/RecipeDataManager.js index 0c4938c5..6614d4d5 100644 --- a/static/js/managers/import/RecipeDataManager.js +++ b/static/js/managers/import/RecipeDataManager.js @@ -226,40 +226,36 @@ export class RecipeDataManager { } }; - // Generate the HTML for duplicate recipes + // Generate the HTML for duplicate recipes warning duplicateContainer.innerHTML = `
- ${this.importManager.duplicateRecipes.length} similar ${this.importManager.duplicateRecipes.length === 1 ? 'recipe' : 'recipes'} found in your library + ${this.importManager.duplicateRecipes.length} identical ${this.importManager.duplicateRecipes.length === 1 ? 'recipe' : 'recipes'} found in your library
- These recipes contain the same LoRAs with similar weights. + These recipes contain the same LoRAs with identical weights. +
-
- ${this.importManager.duplicateRecipes.map((recipe, index) => ` -
+ - - -
+ + +