diff --git a/py/routes/handlers/recipe_handlers.py b/py/routes/handlers/recipe_handlers.py index 7d0574a0..e34b662f 100644 --- a/py/routes/handlers/recipe_handlers.py +++ b/py/routes/handlers/recipe_handlers.py @@ -461,7 +461,11 @@ class RecipeQueryHandler: if recipe_scanner is None: raise RuntimeError("Recipe scanner unavailable") - self._logger.info("Manually triggering recipe cache rebuild") + full_rebuild = request.query.get("full_rebuild", "true").lower() == "true" + self._logger.info( + "Manually triggering recipe cache %s", + "full rebuild" if full_rebuild else "refresh", + ) await recipe_scanner.get_cached_data(force_refresh=True) return web.json_response( {"success": True, "message": "Recipe cache refreshed successfully"} diff --git a/static/js/api/recipeApi.js b/static/js/api/recipeApi.js index 5cbddc7a..5a817a12 100644 --- a/static/js/api/recipeApi.js +++ b/static/js/api/recipeApi.js @@ -294,47 +294,37 @@ export async function resetAndReload(updateFolders = false, options = {}) { } /** - * Sync changes - quick refresh without rebuilding cache (similar to models page) + * Refreshes the recipe list by triggering a backend scan, then reloading. + * @param {boolean} fullRebuild - If true, fully rebuild the cache; if false, incremental scan */ -export async function syncChanges() { +export async function refreshRecipes(fullRebuild = true) { + const actionLabel = fullRebuild ? 'Rebuilding recipe cache' : 'Refreshing recipes'; + const actionToast = fullRebuild ? 'Full rebuild' : 'Refresh'; + try { - state.loadingManager.showSimpleLoading('Syncing changes...'); + state.loadingManager.show(`${actionLabel}...`, 0); - // Simply reload the recipes without rebuilding cache - await resetAndReload(false); + const url = new URL(RECIPE_ENDPOINTS.scan, window.location.origin); + url.searchParams.append('full_rebuild', fullRebuild); - showToast('toast.recipes.syncComplete', {}, 'success'); - } catch (error) { - console.error('Error syncing recipes:', error); - showToast('toast.recipes.syncFailed', { message: error.message }, 'error'); - } finally { - state.loadingManager.hide(); - state.loadingManager.restoreProgressBar(); - } -} - -/** - * Refreshes the recipe list by first rebuilding the cache and then loading recipes - */ -export async function refreshRecipes() { - try { - state.loadingManager.showSimpleLoading('Refreshing recipes...'); - - // Call the API endpoint to rebuild the recipe cache - const response = await fetch(RECIPE_ENDPOINTS.scan); + const response = await fetch(url); if (!response.ok) { - const data = await response.json(); - throw new Error(data.error || 'Failed to refresh recipe cache'); + throw new Error(`Failed to refresh recipe cache: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.status === 'cancelled') { + showToast('toast.api.operationCancelled', {}, 'info'); + return; } - // After successful cache rebuild, reload the recipes await resetAndReload(false); - showToast('toast.recipes.refreshComplete', {}, 'success'); + showToast('toast.api.refreshComplete', { action: actionToast }, 'success'); } catch (error) { console.error('Error refreshing recipes:', error); - showToast('toast.recipes.refreshFailed', { message: error.message }, 'error'); + showToast('toast.api.refreshFailed', { action: fullRebuild ? 'rebuild' : 'refresh', type: 'recipe' }, 'error'); } finally { state.loadingManager.hide(); state.loadingManager.restoreProgressBar(); diff --git a/static/js/recipes.js b/static/js/recipes.js index 54956167..f3d03728 100644 --- a/static/js/recipes.js +++ b/static/js/recipes.js @@ -8,7 +8,7 @@ import { getSessionItem, removeSessionItem } from './utils/storageHelpers.js'; import { RecipeContextMenu } from './components/ContextMenu/index.js'; import { DuplicatesManager } from './components/DuplicatesManager.js'; import { refreshVirtualScroll } from './utils/infiniteScroll.js'; -import { refreshRecipes, syncChanges, RecipeSidebarApiClient } from './api/recipeApi.js'; +import { refreshRecipes, RecipeSidebarApiClient } from './api/recipeApi.js'; import { sidebarManager } from './components/SidebarManager.js'; class RecipePageControls { @@ -23,12 +23,9 @@ class RecipePageControls { } async refreshModels(fullRebuild = false) { - if (fullRebuild) { - await refreshRecipes(); - return; - } + await refreshRecipes(fullRebuild); - await syncChanges(); + await sidebarManager.refresh(); } getSidebarApiClient() {