diff --git a/static/js/api/apiConfig.js b/static/js/api/apiConfig.js index 53b3f842..d64769ba 100644 --- a/static/js/api/apiConfig.js +++ b/static/js/api/apiConfig.js @@ -26,7 +26,7 @@ export const MODEL_CONFIG = { [MODEL_TYPES.CHECKPOINT]: { displayName: 'Checkpoint', singularName: 'checkpoint', - defaultPageSize: 50, + defaultPageSize: 100, supportsLetterFilter: false, supportsBulkOperations: true, supportsMove: false, diff --git a/static/js/api/checkpointApi.js b/static/js/api/checkpointApi.js deleted file mode 100644 index 60f0a3ef..00000000 --- a/static/js/api/checkpointApi.js +++ /dev/null @@ -1,39 +0,0 @@ -import { createModelApiClient } from './baseModelApi.js'; -import { MODEL_TYPES } from './apiConfig.js'; - -// Create Checkpoint-specific API client -const checkpointApiClient = createModelApiClient(MODEL_TYPES.CHECKPOINT); - -// Export all common operations using the unified client -export const deleteModel = (filePath) => checkpointApiClient.deleteModel(filePath); -export const excludeCheckpoint = (filePath) => checkpointApiClient.excludeModel(filePath); -export const renameCheckpointFile = (filePath, newFileName) => checkpointApiClient.renameModelFile(filePath, newFileName); -export const replacePreview = (filePath) => checkpointApiClient.replaceModelPreview(filePath); -export const saveModelMetadata = (filePath, data) => checkpointApiClient.saveModelMetadata(filePath, data); -export const refreshCheckpoints = (fullRebuild = false) => checkpointApiClient.refreshModels(fullRebuild); -export const refreshSingleCheckpointMetadata = (filePath) => checkpointApiClient.refreshSingleModelMetadata(filePath); -export const fetchCivitai = () => checkpointApiClient.fetchCivitaiMetadata(); - -// Pagination functions -export const fetchCheckpointsPage = (page = 1, pageSize = 50) => checkpointApiClient.fetchModelsPage(page, pageSize); - -// Virtual scrolling operations -export async function loadMoreCheckpoints(resetPage = false, updateFolders = false) { - return checkpointApiClient.loadMoreWithVirtualScroll(resetPage, updateFolders); -} - -// Checkpoint-specific functions -export async function getCheckpointInfo(name) { - try { - const response = await fetch(`${checkpointApiClient.apiConfig.endpoints.specific.info}/${encodeURIComponent(name)}`); - - if (!response.ok) { - throw new Error(`Failed to fetch checkpoint info: ${response.statusText}`); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching checkpoint info:', error); - throw error; - } -} \ No newline at end of file diff --git a/static/js/api/loraApi.js b/static/js/api/loraApi.js deleted file mode 100644 index cc4ec125..00000000 --- a/static/js/api/loraApi.js +++ /dev/null @@ -1,84 +0,0 @@ -import { createModelApiClient } from './baseModelApi.js'; -import { MODEL_TYPES } from './apiConfig.js'; - -// Create LoRA-specific API client -const loraApiClient = createModelApiClient(MODEL_TYPES.LORA); - -// Export all common operations using the unified client -export const deleteModel = (filePath) => loraApiClient.deleteModel(filePath); -export const excludeLora = (filePath) => loraApiClient.excludeModel(filePath); -export const renameLoraFile = (filePath, newFileName) => loraApiClient.renameModelFile(filePath, newFileName); -export const replacePreview = (filePath) => loraApiClient.replaceModelPreview(filePath); -export const saveModelMetadata = (filePath, data) => loraApiClient.saveModelMetadata(filePath, data); -export const refreshLoras = (fullRebuild = false) => loraApiClient.refreshModels(fullRebuild); -export const refreshSingleLoraMetadata = (filePath) => loraApiClient.refreshSingleModelMetadata(filePath); -export const fetchCivitai = () => loraApiClient.fetchCivitaiMetadata(); - -// Pagination functions -export const fetchLorasPage = (page = 1, pageSize = 100) => loraApiClient.fetchModelsPage(page, pageSize); - -// Virtual scrolling operations -export async function loadMoreLoras(resetPage = false, updateFolders = false) { - return loraApiClient.loadMoreWithVirtualScroll(resetPage, updateFolders); -} - -// LoRA-specific functions that don't have common equivalents -export async function fetchModelDescription(modelId, filePath) { - try { - const response = await fetch(`${loraApiClient.apiConfig.endpoints.specific.modelDescription}?model_id=${modelId}&file_path=${encodeURIComponent(filePath)}`); - - if (!response.ok) { - throw new Error(`Failed to fetch model description: ${response.statusText}`); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching model description:', error); - throw error; - } -} - -// Move operations (LoRA-specific) -export async function moveModel(filePath, targetPath) { - try { - const response = await fetch(loraApiClient.apiConfig.endpoints.specific.moveModel, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - file_path: filePath, - target_path: targetPath - }) - }); - - if (!response.ok) { - throw new Error('Failed to move model'); - } - - return await response.json(); - } catch (error) { - console.error('Error moving model:', error); - throw error; - } -} - -export async function moveModelsBulk(filePaths, targetPath) { - try { - const response = await fetch(loraApiClient.apiConfig.endpoints.specific.moveBulk, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - file_paths: filePaths, - target_path: targetPath - }) - }); - - if (!response.ok) { - throw new Error('Failed to move models'); - } - - return await response.json(); - } catch (error) { - console.error('Error moving models in bulk:', error); - throw error; - } -} \ No newline at end of file diff --git a/static/js/checkpoints.js b/static/js/checkpoints.js index cbc02ace..89fab5b3 100644 --- a/static/js/checkpoints.js +++ b/static/js/checkpoints.js @@ -1,7 +1,6 @@ import { appCore } from './core.js'; import { confirmDelete, closeDeleteModal, confirmExclude, closeExcludeModal } from './utils/modalUtils.js'; import { createPageControls } from './components/controls/index.js'; -import { loadMoreCheckpoints } from './api/checkpointApi.js'; import { CheckpointContextMenu } from './components/ContextMenu/index.js'; import { ModelDuplicatesManager } from './components/ModelDuplicatesManager.js'; import { MODEL_TYPES } from './api/apiConfig.js'; @@ -26,11 +25,6 @@ class CheckpointsPageManager { window.confirmExclude = confirmExclude; window.closeExcludeModal = closeExcludeModal; - // Add loadCheckpoints function to window for FilterManager compatibility - window.checkpointManager = { - loadCheckpoints: (reset) => loadMoreCheckpoints(reset) - }; - // Expose duplicates manager window.modelDuplicatesManager = this.duplicatesManager; } diff --git a/static/js/components/ContextMenu/LoraContextMenu.js b/static/js/components/ContextMenu/LoraContextMenu.js index 2cd43194..28f9c1d9 100644 --- a/static/js/components/ContextMenu/LoraContextMenu.js +++ b/static/js/components/ContextMenu/LoraContextMenu.js @@ -1,7 +1,6 @@ import { BaseContextMenu } from './BaseContextMenu.js'; import { ModelContextMenuMixin } from './ModelContextMenuMixin.js'; -import { refreshSingleLoraMetadata, saveModelMetadata, replacePreview } from '../../api/loraApi.js'; -import { resetAndReload } from '../../api/baseModelApi.js'; +import { getModelApiClient, resetAndReload } from '../../api/baseModelApi.js'; import { copyToClipboard, sendLoraToWorkflow } from '../../utils/uiHelpers.js'; import { showExcludeModal, showDeleteModal } from '../../utils/modalUtils.js'; @@ -20,7 +19,7 @@ export class LoraContextMenu extends BaseContextMenu { // Use the saveModelMetadata implementation from loraApi async saveModelMetadata(filePath, data) { - return saveModelMetadata(filePath, data); + return getModelApiClient().saveModelMetadata(filePath, data); } handleMenuAction(action, menuItem) { @@ -49,7 +48,7 @@ export class LoraContextMenu extends BaseContextMenu { break; case 'replace-preview': // Add a new action for replacing preview images - replacePreview(this.currentCard.dataset.filepath); + getModelApiClient().replaceModelPreview(this.currentCard.dataset.filepath); break; case 'delete': // Call showDeleteModal directly instead of clicking the trash button @@ -59,7 +58,7 @@ export class LoraContextMenu extends BaseContextMenu { moveManager.showMoveModal(this.currentCard.dataset.filepath); break; case 'refresh-metadata': - refreshSingleLoraMetadata(this.currentCard.dataset.filepath); + getModelApiClient().refreshSingleModelMetadata(this.currentCard.dataset.filepath); break; case 'exclude': showExcludeModal(this.currentCard.dataset.filepath); diff --git a/static/js/components/controls/CheckpointsControls.js b/static/js/components/controls/CheckpointsControls.js index ba1a6ff3..492434dc 100644 --- a/static/js/components/controls/CheckpointsControls.js +++ b/static/js/components/controls/CheckpointsControls.js @@ -1,7 +1,6 @@ // CheckpointsControls.js - Specific implementation for the Checkpoints page import { PageControls } from './PageControls.js'; -import { loadMoreCheckpoints, refreshCheckpoints, fetchCivitai } from '../../api/checkpointApi.js'; -import { resetAndReload } from '../../api/baseModelApi.js'; +import { getModelApiClient, resetAndReload } from '../../api/baseModelApi.js'; import { showToast } from '../../utils/uiHelpers.js'; import { downloadManager } from '../../managers/DownloadManager.js'; @@ -24,7 +23,7 @@ export class CheckpointsControls extends PageControls { const checkpointsAPI = { // Core API functions loadMoreModels: async (resetPage = false, updateFolders = false) => { - return await loadMoreCheckpoints(resetPage, updateFolders); + return await getModelApiClient().loadMoreWithVirtualScroll(resetPage, updateFolders); }, resetAndReload: async (updateFolders = false) => { @@ -32,12 +31,12 @@ export class CheckpointsControls extends PageControls { }, refreshModels: async (fullRebuild = false) => { - return await refreshCheckpoints(fullRebuild); + return await getModelApiClient().refreshModels(fullRebuild); }, // Add fetch from Civitai functionality for checkpoints fetchFromCivitai: async () => { - return await fetchCivitai(); + return await getModelApiClient().fetchCivitaiMetadata(); }, // Add show download modal functionality diff --git a/static/js/components/controls/LorasControls.js b/static/js/components/controls/LorasControls.js index d3fa03ad..8ec51983 100644 --- a/static/js/components/controls/LorasControls.js +++ b/static/js/components/controls/LorasControls.js @@ -1,7 +1,6 @@ // LorasControls.js - Specific implementation for the LoRAs page import { PageControls } from './PageControls.js'; -import { loadMoreLoras, fetchCivitai, refreshLoras } from '../../api/loraApi.js'; -import { resetAndReload } from '../../api/baseModelApi.js'; +import { getModelApiClient, resetAndReload } from '../../api/baseModelApi.js'; import { getSessionItem, removeSessionItem } from '../../utils/storageHelpers.js'; import { createAlphabetBar } from '../alphabet/index.js'; import { downloadManager } from '../../managers/DownloadManager.js'; @@ -31,7 +30,7 @@ export class LorasControls extends PageControls { const lorasAPI = { // Core API functions loadMoreModels: async (resetPage = false, updateFolders = false) => { - return await loadMoreLoras(resetPage, updateFolders); + return await getModelApiClient().loadMoreWithVirtualScroll(resetPage, updateFolders); }, resetAndReload: async (updateFolders = false) => { @@ -39,12 +38,12 @@ export class LorasControls extends PageControls { }, refreshModels: async (fullRebuild = false) => { - return await refreshLoras(fullRebuild); + return await getModelApiClient().refreshModels(fullRebuild); }, // LoRA-specific API functions fetchFromCivitai: async () => { - return await fetchCivitai(); + return await getModelApiClient().fetchCivitaiMetadata(); }, showDownloadModal: () => { diff --git a/static/js/loras.js b/static/js/loras.js index 537ed628..5587d2e6 100644 --- a/static/js/loras.js +++ b/static/js/loras.js @@ -1,6 +1,5 @@ import { appCore } from './core.js'; import { state } from './state/index.js'; -import { loadMoreLoras } from './api/loraApi.js'; import { updateCardsForBulkMode } from './components/LoraCard.js'; import { bulkManager } from './managers/BulkManager.js'; import { moveManager } from './managers/MoveManager.js'; @@ -30,7 +29,6 @@ class LoraPageManager { _exposeRequiredGlobalFunctions() { // Only expose what's still needed globally // Most functionality is now handled by the PageControls component - window.loadMoreLoras = loadMoreLoras; window.confirmDelete = confirmDelete; window.closeDeleteModal = closeDeleteModal; window.confirmExclude = confirmExclude; diff --git a/static/js/managers/FilterManager.js b/static/js/managers/FilterManager.js index 86a880b2..4bfe3de4 100644 --- a/static/js/managers/FilterManager.js +++ b/static/js/managers/FilterManager.js @@ -1,8 +1,7 @@ import { BASE_MODEL_CLASSES } from '../utils/constants.js'; import { getCurrentPageState } from '../state/index.js'; import { showToast, updatePanelPositions } from '../utils/uiHelpers.js'; -import { loadMoreLoras } from '../api/loraApi.js'; -import { loadMoreCheckpoints } from '../api/checkpointApi.js'; +import { getModelApiClient } from '../api/baseModelApi.js'; import { removeStorageItem, setStorageItem, getStorageItem } from '../utils/storageHelpers.js'; export class FilterManager { @@ -281,11 +280,9 @@ export class FilterManager { // Call the appropriate manager's load method based on page type if (this.currentPage === 'recipes' && window.recipeManager) { await window.recipeManager.loadRecipes(true); - } else if (this.currentPage === 'loras') { - // For loras page, reset the page and reload - await loadMoreLoras(true, true); - } else if (this.currentPage === 'checkpoints' && window.checkpointManager) { - await loadMoreCheckpoints(true); + } else if (this.currentPage === 'loras' || this.currentPage === 'embeddings' || this.currentPage === 'checkpoints') { + // For models page, reset the page and reload + await getModelApiClient().loadMoreWithVirtualScroll(true, false); } // Update filter button to show active state @@ -339,10 +336,8 @@ export class FilterManager { // Reload data using the appropriate method for the current page if (this.currentPage === 'recipes' && window.recipeManager) { await window.recipeManager.loadRecipes(true); - } else if (this.currentPage === 'loras') { - await loadMoreLoras(true, true); - } else if (this.currentPage === 'checkpoints') { - await loadMoreCheckpoints(true); + } else if (this.currentPage === 'loras' || this.currentPage === 'checkpoints' || this.currentPage === 'embeddings') { + await getModelApiClient().loadMoreWithVirtualScroll(true, true); } showToast(`Filters cleared`, 'info'); diff --git a/static/js/managers/SearchManager.js b/static/js/managers/SearchManager.js index 46c9a247..819bfaa9 100644 --- a/static/js/managers/SearchManager.js +++ b/static/js/managers/SearchManager.js @@ -1,5 +1,6 @@ import { updatePanelPositions } from "../utils/uiHelpers.js"; import { getCurrentPageState } from "../state/index.js"; +import { getModelApiClient } from "../api/baseModelApi.js"; import { setStorageItem, getStorageItem } from "../utils/storageHelpers.js"; /** * SearchManager - Handles search functionality across different pages @@ -332,15 +333,9 @@ export class SearchManager { // Call the appropriate manager's load method based on page type if (this.currentPage === 'recipes' && window.recipeManager) { window.recipeManager.loadRecipes(true); // true to reset pagination - } else if (this.currentPage === 'loras' && window.loadMoreLoras) { - // Reset loras page and reload - if (pageState) { - pageState.currentPage = 1; - pageState.hasMore = true; - } - window.loadMoreLoras(true); // true to reset pagination - } else if (this.currentPage === 'checkpoints' && window.checkpointManager) { - window.checkpointManager.loadCheckpoints(true); // true to reset pagination + } else if (this.currentPage === 'loras' || this.currentPage === 'embeddings' || this.currentPage === 'checkpoints') { + // For models page, reset the page and reload + getModelApiClient().loadMoreWithVirtualScroll(true, false); } } } \ No newline at end of file diff --git a/static/js/utils/infiniteScroll.js b/static/js/utils/infiniteScroll.js index 48876487..da652014 100644 --- a/static/js/utils/infiniteScroll.js +++ b/static/js/utils/infiniteScroll.js @@ -2,8 +2,7 @@ import { state, getCurrentPageState } from '../state/index.js'; import { VirtualScroller } from './VirtualScroller.js'; import { createLoraCard, setupLoraCardEventDelegation } from '../components/LoraCard.js'; import { createCheckpointCard, setupCheckpointCardEventDelegation } from '../components/CheckpointCard.js'; -import { fetchLorasPage } from '../api/loraApi.js'; -import { fetchCheckpointsPage } from '../api/checkpointApi.js'; +import { getModelApiClient } from '../api/baseModelApi.js'; import { showToast } from './uiHelpers.js'; // Function to dynamically import the appropriate card creator based on page type @@ -31,14 +30,12 @@ async function getCardCreator(pageType) { // Function to get the appropriate data fetcher based on page type async function getDataFetcher(pageType) { - if (pageType === 'loras') { - return fetchLorasPage; + if (pageType === 'loras' || pageType === 'embeddings' || pageType === 'checkpoints') { + return (page = 1, pageSize = 100) => getModelApiClient().fetchModelsPage(page, pageSize); } else if (pageType === 'recipes') { // Import the recipeApi module and use the fetchRecipesPage function const { fetchRecipesPage } = await import('../api/recipeApi.js'); return fetchRecipesPage; - } else if (pageType === 'checkpoints') { - return fetchCheckpointsPage; } return null; }