From a88b0239eb01f6f0a61981b29ebc13d23692c91a Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 20 Mar 2025 09:54:13 +0800 Subject: [PATCH] Refactor panel position management and enhance recipe card handling - Removed redundant updatePanelPositions calls from various components and centralized the logic in the uiHelpers.js for better maintainability. - Introduced appendRecipeCards function in RecipeManager to streamline the addition of recipe cards from search results. - Cleaned up unused code related to search input handling and recipe loading, improving overall code clarity and performance. - Updated HeaderManager and SearchManager to utilize the new updatePanelPositions function, ensuring consistent panel positioning across the application. --- static/js/components/Header.js | 51 +------------------- static/js/core.js | 11 +---- static/js/managers/FilterManager.js | 8 +--- static/js/managers/RecipeFilterManager.js | 8 +--- static/js/managers/RecipeSearchManager.js | 33 ++----------- static/js/managers/SearchManager.js | 58 ++--------------------- static/js/recipes.js | 28 +++-------- static/js/utils/uiHelpers.js | 51 ++++++++++++++------ templates/recipes.html | 10 ---- 9 files changed, 56 insertions(+), 202 deletions(-) diff --git a/static/js/components/Header.js b/static/js/components/Header.js index 4c567560..710abb24 100644 --- a/static/js/components/Header.js +++ b/static/js/components/Header.js @@ -101,53 +101,4 @@ export class HeaderManager { }); } } - - // Helper method to update panel positions (can be called from window resize handlers) - updatePanelPositions() { - if (this.searchManager && typeof this.searchManager.updatePanelPositions === 'function') { - this.searchManager.updatePanelPositions(); - } else { - const searchOptionsPanel = document.getElementById('searchOptionsPanel'); - const filterPanel = document.getElementById('filterPanel'); - - if (!searchOptionsPanel && !filterPanel) return; - - // Get the header element - const header = document.querySelector('.app-header'); - if (!header) return; - - // Calculate the position based on the bottom of the header - const headerRect = header.getBoundingClientRect(); - const topPosition = headerRect.bottom + 5; // Add 5px padding - - // Set the positions - if (searchOptionsPanel) { - searchOptionsPanel.style.top = `${topPosition}px`; - } - - if (filterPanel) { - filterPanel.style.top = `${topPosition}px`; - } - - // Adjust panel horizontal position based on the search container - const searchContainer = document.querySelector('.header-search'); - if (searchContainer) { - const searchRect = searchContainer.getBoundingClientRect(); - - // Position the search options panel aligned with the search container - if (searchOptionsPanel) { - searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`; - } - - // Position the filter panel aligned with the filter button - if (filterPanel) { - const filterButton = document.getElementById('filterButton'); - if (filterButton) { - const filterRect = filterButton.getBoundingClientRect(); - filterPanel.style.right = `${window.innerWidth - filterRect.right}px`; - } - } - } - } - } - } +} diff --git a/static/js/core.js b/static/js/core.js index 78abffb9..3485e01e 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -5,7 +5,7 @@ import { modalManager } from './managers/ModalManager.js'; import { updateService } from './managers/UpdateService.js'; import { HeaderManager } from './components/Header.js'; import { SettingsManager } from './managers/SettingsManager.js'; -import { showToast, initTheme, initBackToTop, updatePanelPositions, lazyLoadImages } from './utils/uiHelpers.js'; +import { showToast, initTheme, initBackToTop, lazyLoadImages } from './utils/uiHelpers.js'; import { initializeInfiniteScroll } from './utils/infiniteScroll.js'; // Core application class @@ -30,12 +30,6 @@ export class AppCore { initTheme(); initBackToTop(); - // Set up event listeners - window.addEventListener('resize', updatePanelPositions); - - // Initial positioning - updatePanelPositions(); - // Mark as initialized this.initialized = true; @@ -66,9 +60,6 @@ export class AppCore { initializeInfiniteScroll(pageType); } - // Update panel positions - updatePanelPositions(); - return this; } } diff --git a/static/js/managers/FilterManager.js b/static/js/managers/FilterManager.js index e691da24..5be55328 100644 --- a/static/js/managers/FilterManager.js +++ b/static/js/managers/FilterManager.js @@ -1,6 +1,6 @@ import { BASE_MODELS, BASE_MODEL_CLASSES } from '../utils/constants.js'; import { state, getCurrentPageState } from '../state/index.js'; -import { showToast } from '../utils/uiHelpers.js'; +import { showToast, updatePanelPositions } from '../utils/uiHelpers.js'; import { resetAndReload } from '../api/loraApi.js'; export class FilterManager { @@ -155,11 +155,7 @@ export class FilterManager { if (isHidden) { // Update panel positions before showing - if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') { - window.searchManager.updatePanelPositions(); - } else if (typeof updatePanelPositions === 'function') { - updatePanelPositions(); - } + updatePanelPositions(); this.filterPanel.classList.remove('hidden'); this.filterButton.classList.add('active'); diff --git a/static/js/managers/RecipeFilterManager.js b/static/js/managers/RecipeFilterManager.js index cc661e8e..5cb5fc73 100644 --- a/static/js/managers/RecipeFilterManager.js +++ b/static/js/managers/RecipeFilterManager.js @@ -1,4 +1,4 @@ -import { showToast } from '../utils/uiHelpers.js'; +import { showToast, updatePanelPositions } from '../utils/uiHelpers.js'; export class RecipeFilterManager { constructor() { @@ -165,11 +165,7 @@ export class RecipeFilterManager { if (isHidden) { // Update panel positions before showing - if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') { - window.searchManager.updatePanelPositions(); - } else if (typeof updatePanelPositions === 'function') { - updatePanelPositions(); - } + updatePanelPositions(); this.filterPanel.classList.remove('hidden'); this.filterButton.classList.add('active'); diff --git a/static/js/managers/RecipeSearchManager.js b/static/js/managers/RecipeSearchManager.js index 13de63d7..93dd6f2b 100644 --- a/static/js/managers/RecipeSearchManager.js +++ b/static/js/managers/RecipeSearchManager.js @@ -33,10 +33,7 @@ export class RecipeSearchManager extends SearchManager { const grid = document.getElementById('recipeGrid'); if (!searchTerm) { - if (state) { - state.pages.recipes.currentPage = 1; - } - this.resetAndReloadRecipes(); + window.recipeManager.loadRecipes(); return; } @@ -112,34 +109,12 @@ export class RecipeSearchManager extends SearchManager { } } - resetAndReloadRecipes() { - if (window.recipeManager && typeof window.recipeManager.loadRecipes === 'function') { - window.recipeManager.loadRecipes(); - } else { - // Fallback to reloading the page - window.location.reload(); - } - } - appendRecipeCards(recipes) { - // This function would be implemented in the recipes page - // Similar to appendLoraCards for loras const grid = document.getElementById('recipeGrid'); if (!grid) return; - if (typeof window.appendRecipeCards === 'function') { - window.appendRecipeCards(recipes); - } else { - // Fallback implementation - recipes.forEach(recipe => { - const card = document.createElement('div'); - card.className = 'recipe-card'; - card.innerHTML = ` -

${recipe.name}

-

${recipe.description || 'No description'}

- `; - grid.appendChild(card); - }); - } + // Create data object in the format expected by the RecipeManager + const data = { items: recipes, has_more: false }; + window.recipeManager.updateRecipesGrid(data, false); } } \ No newline at end of file diff --git a/static/js/managers/SearchManager.js b/static/js/managers/SearchManager.js index 54628a43..0dc552ba 100644 --- a/static/js/managers/SearchManager.js +++ b/static/js/managers/SearchManager.js @@ -1,3 +1,4 @@ +import { updatePanelPositions } from "../utils/uiHelpers.js"; /** * SearchManager - Handles search functionality across different pages * Each page can extend or customize this base functionality @@ -27,11 +28,10 @@ export class SearchManager { this.initEventListeners(); this.loadSearchPreferences(); - // Initialize panel positions - this.updatePanelPositions(); + updatePanelPositions(); // Add resize listener - window.addEventListener('resize', this.updatePanelPositions.bind(this)); + window.addEventListener('resize', updatePanelPositions); } initEventListeners() { @@ -161,7 +161,7 @@ export class SearchManager { const isHidden = this.searchOptionsPanel.classList.contains('hidden'); if (isHidden) { // Update position before showing - this.updatePanelPositions(); + updatePanelPositions(); this.searchOptionsPanel.classList.remove('hidden'); this.searchOptionsToggle.classList.add('active'); @@ -267,56 +267,6 @@ export class SearchManager { return options; } - updatePanelPositions() { - const searchOptionsPanel = document.getElementById('searchOptionsPanel'); - const filterPanel = document.getElementById('filterPanel'); - - if (!searchOptionsPanel && !filterPanel) return; - - // Get the header element - const header = document.querySelector('.app-header'); - if (!header) return; - - // Calculate the position based on the bottom of the header - const headerRect = header.getBoundingClientRect(); - const topPosition = headerRect.bottom + 5; // Add 5px padding - - // Set the positions - if (searchOptionsPanel) { - searchOptionsPanel.style.top = `${topPosition}px`; - - // Make sure the panel is visible when positioned - if (!searchOptionsPanel.classList.contains('hidden') && - window.getComputedStyle(searchOptionsPanel).display === 'none') { - searchOptionsPanel.style.display = 'block'; - } - } - - if (filterPanel) { - filterPanel.style.top = `${topPosition}px`; - } - - // Adjust panel horizontal position based on the search container - const searchContainer = document.querySelector('.header-search'); - if (searchContainer) { - const searchRect = searchContainer.getBoundingClientRect(); - - // Position the search options panel aligned with the search container - if (searchOptionsPanel) { - searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`; - } - - // Position the filter panel aligned with the filter button - if (filterPanel) { - const filterButton = document.getElementById('filterButton'); - if (filterButton) { - const filterRect = filterButton.getBoundingClientRect(); - filterPanel.style.right = `${window.innerWidth - filterRect.right}px`; - } - } - } - } - performSearch() { const query = this.searchInput.value.trim(); const options = this.getActiveSearchOptions(); diff --git a/static/js/recipes.js b/static/js/recipes.js index db474bb0..3598d8fc 100644 --- a/static/js/recipes.js +++ b/static/js/recipes.js @@ -59,6 +59,12 @@ class RecipeManager { window.importRecipes = () => this.importRecipes(); window.importManager = this.importManager; window.loadMoreRecipes = () => this.loadMoreRecipes(); + + // Add appendRecipeCards function for the search manager to use + window.appendRecipeCards = (recipes) => { + const data = { items: recipes, has_more: false }; + this.updateRecipesGrid(data, false); + }; } initEventListeners() { @@ -70,28 +76,6 @@ class RecipeManager { this.loadRecipes(); }); } - - // Search input - const searchInput = document.getElementById('searchInput'); - if (searchInput) { - let debounceTimeout; - searchInput.addEventListener('input', () => { - clearTimeout(debounceTimeout); - debounceTimeout = setTimeout(() => { - this.pageState.filters.search = searchInput.value; - this.loadRecipes(); - }, 300); - }); - } - - // Import button - const importButton = document.querySelector('button[onclick="importRecipes()"]'); - if (importButton) { - importButton.onclick = (e) => { - e.preventDefault(); - this.importManager.showImportModal(); - }; - } } async loadRecipes(resetPage = true) { diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index cd8d1435..84600910 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -106,20 +106,45 @@ export function updatePanelPositions() { const searchOptionsPanel = document.getElementById('searchOptionsPanel'); const filterPanel = document.getElementById('filterPanel'); - if (!searchOptionsPanel || !filterPanel) return; + if (!searchOptionsPanel && !filterPanel) return; - // Get the controls container - const controls = document.querySelector('.controls'); - if (!controls) return; + // Get the header element + const header = document.querySelector('.app-header'); + if (!header) return; - // Calculate the position based on the bottom of the controls container - const controlsRect = controls.getBoundingClientRect(); - const topPosition = controlsRect.bottom + 10; // Add 10px padding + // Calculate the position based on the bottom of the header + const headerRect = header.getBoundingClientRect(); + const topPosition = headerRect.bottom + 5; // Add 5px padding // Set the positions - searchOptionsPanel.style.top = `${topPosition}px`; - filterPanel.style.top = `${topPosition}px`; -} + if (searchOptionsPanel) { + searchOptionsPanel.style.top = `${topPosition}px`; + } + + if (filterPanel) { + filterPanel.style.top = `${topPosition}px`; + } + + // Adjust panel horizontal position based on the search container + const searchContainer = document.querySelector('.header-search'); + if (searchContainer) { + const searchRect = searchContainer.getBoundingClientRect(); + + // Position the search options panel aligned with the search container + if (searchOptionsPanel) { + searchOptionsPanel.style.right = `${window.innerWidth - searchRect.right}px`; + } + + // Position the filter panel aligned with the filter button + if (filterPanel) { + const filterButton = document.getElementById('filterButton'); + if (filterButton) { + const filterRect = filterButton.getBoundingClientRect(); + filterPanel.style.right = `${window.innerWidth - filterRect.right}px`; + } + } + } + } // Update the toggleFolderTags function export function toggleFolderTags() { @@ -144,11 +169,7 @@ export function toggleFolderTags() { // Update panel positions after toggling // Use a small delay to ensure the DOM has updated setTimeout(() => { - if (window.searchManager && typeof window.searchManager.updatePanelPositions === 'function') { - window.searchManager.updatePanelPositions(); - } else if (typeof updatePanelPositions === 'function') { - updatePanelPositions(); - } + updatePanelPositions(); }, 50); } } diff --git a/templates/recipes.html b/templates/recipes.html index 4c00961a..451ac97e 100644 --- a/templates/recipes.html +++ b/templates/recipes.html @@ -76,14 +76,4 @@ {% block main_script %} -{% endblock %} - -{% block additional_scripts %} - {% endblock %} \ No newline at end of file