mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
feat: implement embeddings functionality with context menus, controls, and page management
This commit is contained in:
@@ -206,6 +206,20 @@ class MetadataManager:
|
|||||||
model_type="checkpoint",
|
model_type="checkpoint",
|
||||||
from_civitai=True
|
from_civitai=True
|
||||||
)
|
)
|
||||||
|
elif model_class.__name__ == "EmbeddingMetadata":
|
||||||
|
metadata = model_class(
|
||||||
|
file_name=base_name,
|
||||||
|
model_name=base_name,
|
||||||
|
file_path=normalize_path(file_path),
|
||||||
|
size=os.path.getsize(real_path),
|
||||||
|
modified=datetime.now().timestamp(),
|
||||||
|
sha256=sha256,
|
||||||
|
base_model="Unknown",
|
||||||
|
preview_url=normalize_path(preview_url),
|
||||||
|
tags=[],
|
||||||
|
modelDescription="",
|
||||||
|
from_civitai=True
|
||||||
|
)
|
||||||
else: # Default to LoraMetadata
|
else: # Default to LoraMetadata
|
||||||
metadata = model_class(
|
metadata = model_class(
|
||||||
file_name=base_name,
|
file_name=base_name,
|
||||||
|
|||||||
@@ -279,23 +279,50 @@ class StandaloneLoraManager(LoraManager):
|
|||||||
# Record route mapping
|
# Record route mapping
|
||||||
config.add_route_mapping(real_root, preview_path)
|
config.add_route_mapping(real_root, preview_path)
|
||||||
added_targets.add(os.path.normpath(real_root))
|
added_targets.add(os.path.normpath(real_root))
|
||||||
|
|
||||||
|
# Add static routes for each embedding root
|
||||||
|
for idx, root in enumerate(getattr(config, "embeddings_roots", []), start=1):
|
||||||
|
if not os.path.exists(root):
|
||||||
|
logger.warning(f"Embedding root path does not exist: {root}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
preview_path = f'/embeddings_static/root{idx}/preview'
|
||||||
|
|
||||||
|
real_root = root
|
||||||
|
for target, link in config._path_mappings.items():
|
||||||
|
if os.path.normpath(link) == os.path.normpath(root):
|
||||||
|
real_root = target
|
||||||
|
break
|
||||||
|
|
||||||
|
display_root = real_root.replace('\\', '/')
|
||||||
|
app.router.add_static(preview_path, real_root)
|
||||||
|
logger.info(f"Added static route {preview_path} -> {display_root}")
|
||||||
|
|
||||||
|
config.add_route_mapping(real_root, preview_path)
|
||||||
|
added_targets.add(os.path.normpath(real_root))
|
||||||
|
|
||||||
# Add static routes for symlink target paths that aren't already covered
|
# Add static routes for symlink target paths that aren't already covered
|
||||||
link_idx = {
|
link_idx = {
|
||||||
'lora': 1,
|
'lora': 1,
|
||||||
'checkpoint': 1
|
'checkpoint': 1,
|
||||||
|
'embedding': 1
|
||||||
}
|
}
|
||||||
|
|
||||||
for target_path, link_path in config._path_mappings.items():
|
for target_path, link_path in config._path_mappings.items():
|
||||||
norm_target = os.path.normpath(target_path)
|
norm_target = os.path.normpath(target_path)
|
||||||
if norm_target not in added_targets:
|
if norm_target not in added_targets:
|
||||||
# Determine if this is a checkpoint or lora link based on path
|
# Determine if this is a checkpoint, lora, or embedding link based on path
|
||||||
is_checkpoint = any(os.path.normpath(cp_root) in os.path.normpath(link_path) for cp_root in config.base_models_roots)
|
is_checkpoint = any(os.path.normpath(cp_root) in os.path.normpath(link_path) for cp_root in config.base_models_roots)
|
||||||
is_checkpoint = is_checkpoint or any(os.path.normpath(cp_root) in norm_target for cp_root in config.base_models_roots)
|
is_checkpoint = is_checkpoint or any(os.path.normpath(cp_root) in norm_target for cp_root in config.base_models_roots)
|
||||||
|
is_embedding = any(os.path.normpath(emb_root) in os.path.normpath(link_path) for emb_root in getattr(config, "embeddings_roots", []))
|
||||||
|
is_embedding = is_embedding or any(os.path.normpath(emb_root) in norm_target for emb_root in getattr(config, "embeddings_roots", []))
|
||||||
|
|
||||||
if is_checkpoint:
|
if is_checkpoint:
|
||||||
route_path = f'/checkpoints_static/link_{link_idx["checkpoint"]}/preview'
|
route_path = f'/checkpoints_static/link_{link_idx["checkpoint"]}/preview'
|
||||||
link_idx["checkpoint"] += 1
|
link_idx["checkpoint"] += 1
|
||||||
|
elif is_embedding:
|
||||||
|
route_path = f'/embeddings_static/link_{link_idx["embedding"]}/preview'
|
||||||
|
link_idx["embedding"] += 1
|
||||||
else:
|
else:
|
||||||
route_path = f'/loras_static/link_{link_idx["lora"]}/preview'
|
route_path = f'/loras_static/link_{link_idx["lora"]}/preview'
|
||||||
link_idx["lora"] += 1
|
link_idx["lora"] += 1
|
||||||
|
|||||||
68
static/js/components/ContextMenu/EmbeddingContextMenu.js
Normal file
68
static/js/components/ContextMenu/EmbeddingContextMenu.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { BaseContextMenu } from './BaseContextMenu.js';
|
||||||
|
import { ModelContextMenuMixin } from './ModelContextMenuMixin.js';
|
||||||
|
import { getModelApiClient, resetAndReload } from '../../api/baseModelApi.js';
|
||||||
|
import { showToast } from '../../utils/uiHelpers.js';
|
||||||
|
import { showDeleteModal, showExcludeModal } from '../../utils/modalUtils.js';
|
||||||
|
|
||||||
|
export class EmbeddingContextMenu extends BaseContextMenu {
|
||||||
|
constructor() {
|
||||||
|
super('embeddingContextMenu', '.embedding-card');
|
||||||
|
this.nsfwSelector = document.getElementById('nsfwLevelSelector');
|
||||||
|
this.modelType = 'embedding';
|
||||||
|
this.resetAndReload = resetAndReload;
|
||||||
|
|
||||||
|
// Initialize NSFW Level Selector events
|
||||||
|
if (this.nsfwSelector) {
|
||||||
|
this.initNSFWSelector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation needed by the mixin
|
||||||
|
async saveModelMetadata(filePath, data) {
|
||||||
|
return getModelApiClient().saveModelMetadata(filePath, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMenuAction(action) {
|
||||||
|
// First try to handle with common actions
|
||||||
|
if (ModelContextMenuMixin.handleCommonMenuActions.call(this, action)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiClient = getModelApiClient();
|
||||||
|
|
||||||
|
// Otherwise handle embedding-specific actions
|
||||||
|
switch(action) {
|
||||||
|
case 'details':
|
||||||
|
// Show embedding details
|
||||||
|
this.currentCard.click();
|
||||||
|
break;
|
||||||
|
case 'replace-preview':
|
||||||
|
// Add new action for replacing preview images
|
||||||
|
apiClient.replaceModelPreview(this.currentCard.dataset.filepath);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
showDeleteModal(this.currentCard.dataset.filepath);
|
||||||
|
break;
|
||||||
|
case 'copyname':
|
||||||
|
// Copy embedding name
|
||||||
|
if (this.currentCard.querySelector('.fa-copy')) {
|
||||||
|
this.currentCard.querySelector('.fa-copy').click();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'refresh-metadata':
|
||||||
|
// Refresh metadata from CivitAI
|
||||||
|
apiClient.refreshSingleModelMetadata(this.currentCard.dataset.filepath);
|
||||||
|
break;
|
||||||
|
case 'move':
|
||||||
|
// Move to folder (placeholder)
|
||||||
|
showToast('Move to folder feature coming soon', 'info');
|
||||||
|
break;
|
||||||
|
case 'exclude':
|
||||||
|
showExcludeModal(this.currentCard.dataset.filepath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mix in shared methods
|
||||||
|
Object.assign(EmbeddingContextMenu.prototype, ModelContextMenuMixin);
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export { LoraContextMenu } from './LoraContextMenu.js';
|
export { LoraContextMenu } from './LoraContextMenu.js';
|
||||||
export { RecipeContextMenu } from './RecipeContextMenu.js';
|
export { RecipeContextMenu } from './RecipeContextMenu.js';
|
||||||
export { CheckpointContextMenu } from './CheckpointContextMenu.js';
|
export { CheckpointContextMenu } from './CheckpointContextMenu.js';
|
||||||
|
export { EmbeddingContextMenu } from './EmbeddingContextMenu.js';
|
||||||
export { ModelContextMenuMixin } from './ModelContextMenuMixin.js';
|
export { ModelContextMenuMixin } from './ModelContextMenuMixin.js';
|
||||||
@@ -26,6 +26,7 @@ export class HeaderManager {
|
|||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
if (path.includes('/loras/recipes')) return 'recipes';
|
if (path.includes('/loras/recipes')) return 'recipes';
|
||||||
if (path.includes('/checkpoints')) return 'checkpoints';
|
if (path.includes('/checkpoints')) return 'checkpoints';
|
||||||
|
if (path.includes('/embeddings')) return 'embeddings';
|
||||||
if (path.includes('/statistics')) return 'statistics';
|
if (path.includes('/statistics')) return 'statistics';
|
||||||
if (path.includes('/loras')) return 'loras';
|
if (path.includes('/loras')) return 'loras';
|
||||||
return 'unknown';
|
return 'unknown';
|
||||||
|
|||||||
57
static/js/components/controls/EmbeddingsControls.js
Normal file
57
static/js/components/controls/EmbeddingsControls.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// EmbeddingsControls.js - Specific implementation for the Embeddings page
|
||||||
|
import { PageControls } from './PageControls.js';
|
||||||
|
import { getModelApiClient, resetAndReload } from '../../api/baseModelApi.js';
|
||||||
|
import { showToast } from '../../utils/uiHelpers.js';
|
||||||
|
import { downloadManager } from '../../managers/DownloadManager.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EmbeddingsControls class - Extends PageControls for Embedding-specific functionality
|
||||||
|
*/
|
||||||
|
export class EmbeddingsControls extends PageControls {
|
||||||
|
constructor() {
|
||||||
|
// Initialize with 'embeddings' page type
|
||||||
|
super('embeddings');
|
||||||
|
|
||||||
|
// Register API methods specific to the Embeddings page
|
||||||
|
this.registerEmbeddingsAPI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Embedding-specific API methods
|
||||||
|
*/
|
||||||
|
registerEmbeddingsAPI() {
|
||||||
|
const embeddingsAPI = {
|
||||||
|
// Core API functions
|
||||||
|
loadMoreModels: async (resetPage = false, updateFolders = false) => {
|
||||||
|
return await getModelApiClient().loadMoreWithVirtualScroll(resetPage, updateFolders);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetAndReload: async (updateFolders = false) => {
|
||||||
|
return await resetAndReload(updateFolders);
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshModels: async (fullRebuild = false) => {
|
||||||
|
return await getModelApiClient().refreshModels(fullRebuild);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add fetch from Civitai functionality for embeddings
|
||||||
|
fetchFromCivitai: async () => {
|
||||||
|
return await getModelApiClient().fetchCivitaiMetadata();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add show download modal functionality
|
||||||
|
showDownloadModal: () => {
|
||||||
|
downloadManager.showDownloadModal();
|
||||||
|
},
|
||||||
|
|
||||||
|
// No clearCustomFilter implementation is needed for embeddings
|
||||||
|
// as custom filters are currently only used for LoRAs
|
||||||
|
clearCustomFilter: async () => {
|
||||||
|
showToast('No custom filter to clear', 'info');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register the API
|
||||||
|
this.registerAPI(embeddingsAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,14 @@
|
|||||||
import { PageControls } from './PageControls.js';
|
import { PageControls } from './PageControls.js';
|
||||||
import { LorasControls } from './LorasControls.js';
|
import { LorasControls } from './LorasControls.js';
|
||||||
import { CheckpointsControls } from './CheckpointsControls.js';
|
import { CheckpointsControls } from './CheckpointsControls.js';
|
||||||
|
import { EmbeddingsControls } from './EmbeddingsControls.js';
|
||||||
|
|
||||||
// Export the classes
|
// Export the classes
|
||||||
export { PageControls, LorasControls, CheckpointsControls };
|
export { PageControls, LorasControls, CheckpointsControls, EmbeddingsControls };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory function to create the appropriate controls based on page type
|
* Factory function to create the appropriate controls based on page type
|
||||||
* @param {string} pageType - The type of page ('loras' or 'checkpoints')
|
* @param {string} pageType - The type of page ('loras', 'checkpoints', or 'embeddings')
|
||||||
* @returns {PageControls} - The appropriate controls instance
|
* @returns {PageControls} - The appropriate controls instance
|
||||||
*/
|
*/
|
||||||
export function createPageControls(pageType) {
|
export function createPageControls(pageType) {
|
||||||
@@ -16,6 +17,8 @@ export function createPageControls(pageType) {
|
|||||||
return new LorasControls();
|
return new LorasControls();
|
||||||
} else if (pageType === 'checkpoints') {
|
} else if (pageType === 'checkpoints') {
|
||||||
return new CheckpointsControls();
|
return new CheckpointsControls();
|
||||||
|
} else if (pageType === 'embeddings') {
|
||||||
|
return new EmbeddingsControls();
|
||||||
} else {
|
} else {
|
||||||
console.error(`Unknown page type: ${pageType}`);
|
console.error(`Unknown page type: ${pageType}`);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -33,7 +33,15 @@ export function showModelModal(model, modelType) {
|
|||||||
model.civitai.trainedWords.map(word => word.replace(/'/g, '\\\'')) : [];
|
model.civitai.trainedWords.map(word => word.replace(/'/g, '\\\'')) : [];
|
||||||
|
|
||||||
// Generate model type specific content
|
// Generate model type specific content
|
||||||
const typeSpecificContent = modelType === 'loras' ? renderLoraSpecificContent(model, escapedWords) : '';
|
// const typeSpecificContent = modelType === 'loras' ? renderLoraSpecificContent(model, escapedWords) : '';
|
||||||
|
let typeSpecificContent;
|
||||||
|
if (modelType === 'loras') {
|
||||||
|
typeSpecificContent = renderLoraSpecificContent(model, escapedWords);
|
||||||
|
} else if (modelType === 'embeddings') {
|
||||||
|
typeSpecificContent = renderEmbeddingSpecificContent(model, escapedWords);
|
||||||
|
} else {
|
||||||
|
typeSpecificContent = '';
|
||||||
|
}
|
||||||
|
|
||||||
// Generate tabs based on model type
|
// Generate tabs based on model type
|
||||||
const tabsContent = modelType === 'loras' ?
|
const tabsContent = modelType === 'loras' ?
|
||||||
@@ -248,6 +256,10 @@ function renderLoraSpecificContent(lora, escapedWords) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderEmbeddingSpecificContent(embedding, escapedWords) {
|
||||||
|
return `${renderTriggerWords(escapedWords, embedding.file_path)}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up event handlers using event delegation for LoRA modal
|
* Sets up event handlers using event delegation for LoRA modal
|
||||||
* @param {string} filePath - Path to the model file
|
* @param {string} filePath - Path to the model file
|
||||||
|
|||||||
55
static/js/embeddings.js
Normal file
55
static/js/embeddings.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { appCore } from './core.js';
|
||||||
|
import { confirmDelete, closeDeleteModal, confirmExclude, closeExcludeModal } from './utils/modalUtils.js';
|
||||||
|
import { createPageControls } from './components/controls/index.js';
|
||||||
|
import { EmbeddingContextMenu } from './components/ContextMenu/index.js';
|
||||||
|
import { ModelDuplicatesManager } from './components/ModelDuplicatesManager.js';
|
||||||
|
import { MODEL_TYPES } from './api/apiConfig.js';
|
||||||
|
|
||||||
|
// Initialize the Embeddings page
|
||||||
|
class EmbeddingsPageManager {
|
||||||
|
constructor() {
|
||||||
|
// Initialize page controls
|
||||||
|
this.pageControls = createPageControls(MODEL_TYPES.EMBEDDING);
|
||||||
|
|
||||||
|
// Initialize the ModelDuplicatesManager
|
||||||
|
this.duplicatesManager = new ModelDuplicatesManager(this, MODEL_TYPES.EMBEDDING);
|
||||||
|
|
||||||
|
// Expose only necessary functions to global scope
|
||||||
|
this._exposeRequiredGlobalFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
_exposeRequiredGlobalFunctions() {
|
||||||
|
// Minimal set of functions that need to remain global
|
||||||
|
window.confirmDelete = confirmDelete;
|
||||||
|
window.closeDeleteModal = closeDeleteModal;
|
||||||
|
window.confirmExclude = confirmExclude;
|
||||||
|
window.closeExcludeModal = closeExcludeModal;
|
||||||
|
|
||||||
|
// Expose duplicates manager
|
||||||
|
window.modelDuplicatesManager = this.duplicatesManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
// Initialize page-specific components
|
||||||
|
this.pageControls.restoreFolderFilter();
|
||||||
|
this.pageControls.initFolderTagsVisibility();
|
||||||
|
|
||||||
|
// Initialize context menu
|
||||||
|
new EmbeddingContextMenu();
|
||||||
|
|
||||||
|
// Initialize common page features
|
||||||
|
appCore.initializePageFeatures();
|
||||||
|
|
||||||
|
console.log('Embeddings Manager initialized');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize everything when DOM is ready
|
||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
// Initialize core application
|
||||||
|
await appCore.initialize();
|
||||||
|
|
||||||
|
// Initialize embeddings page
|
||||||
|
const embeddingsPage = new EmbeddingsPageManager();
|
||||||
|
await embeddingsPage.initialize();
|
||||||
|
});
|
||||||
@@ -72,6 +72,8 @@ export class FilterManager {
|
|||||||
tagsEndpoint = '/api/recipes/top-tags?limit=20';
|
tagsEndpoint = '/api/recipes/top-tags?limit=20';
|
||||||
} else if (this.currentPage === 'checkpoints') {
|
} else if (this.currentPage === 'checkpoints') {
|
||||||
tagsEndpoint = '/api/checkpoints/top-tags?limit=20';
|
tagsEndpoint = '/api/checkpoints/top-tags?limit=20';
|
||||||
|
} else if (this.currentPage === 'embeddings') {
|
||||||
|
tagsEndpoint = '/api/embeddings/top-tags?limit=20';
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(tagsEndpoint);
|
const response = await fetch(tagsEndpoint);
|
||||||
@@ -147,6 +149,8 @@ export class FilterManager {
|
|||||||
apiEndpoint = '/api/recipes/base-models';
|
apiEndpoint = '/api/recipes/base-models';
|
||||||
} else if (this.currentPage === 'checkpoints') {
|
} else if (this.currentPage === 'checkpoints') {
|
||||||
apiEndpoint = '/api/checkpoints/base-models';
|
apiEndpoint = '/api/checkpoints/base-models';
|
||||||
|
} else if (this.currentPage === 'embeddings') {
|
||||||
|
apiEndpoint = '/api/embeddings/base-models';
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -160,11 +164,7 @@ export class FilterManager {
|
|||||||
|
|
||||||
data.base_models.forEach(model => {
|
data.base_models.forEach(model => {
|
||||||
const tag = document.createElement('div');
|
const tag = document.createElement('div');
|
||||||
// Add base model classes only for the loras page
|
tag.className = `filter-tag base-model-tag`;
|
||||||
const baseModelClass = (this.currentPage === 'loras' && BASE_MODEL_CLASSES[model.name])
|
|
||||||
? BASE_MODEL_CLASSES[model.name]
|
|
||||||
: '';
|
|
||||||
tag.className = `filter-tag base-model-tag ${baseModelClass}`;
|
|
||||||
tag.dataset.baseModel = model.name;
|
tag.dataset.baseModel = model.name;
|
||||||
tag.innerHTML = `${model.name} <span class="tag-count">${model.count}</span>`;
|
tag.innerHTML = `${model.name} <span class="tag-count">${model.count}</span>`;
|
||||||
|
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ export class SearchManager {
|
|||||||
loraName: options.loraName || false,
|
loraName: options.loraName || false,
|
||||||
loraModel: options.loraModel || false
|
loraModel: options.loraModel || false
|
||||||
};
|
};
|
||||||
} else if (this.currentPage === 'loras') {
|
} else if (this.currentPage === 'loras' || this.currentPage === 'embeddings') {
|
||||||
pageState.searchOptions = {
|
pageState.searchOptions = {
|
||||||
filename: options.filename || false,
|
filename: options.filename || false,
|
||||||
modelname: options.modelname || false,
|
modelname: options.modelname || false,
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
<a href="/checkpoints" class="nav-item" id="checkpointsNavItem">
|
<a href="/checkpoints" class="nav-item" id="checkpointsNavItem">
|
||||||
<i class="fas fa-check-circle"></i> Checkpoints
|
<i class="fas fa-check-circle"></i> Checkpoints
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/embeddings" class="nav-item" id="embeddingsNavItem">
|
||||||
|
<i class="fas fa-code"></i> Embeddings
|
||||||
|
</a>
|
||||||
<a href="/statistics" class="nav-item" id="statisticsNavItem">
|
<a href="/statistics" class="nav-item" id="statisticsNavItem">
|
||||||
<i class="fas fa-chart-bar"></i> Statistics
|
<i class="fas fa-chart-bar"></i> Stats
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -83,6 +86,10 @@
|
|||||||
<div class="search-option-tag active" data-option="filename">Filename</div>
|
<div class="search-option-tag active" data-option="filename">Filename</div>
|
||||||
<div class="search-option-tag active" data-option="modelname">Checkpoint Name</div>
|
<div class="search-option-tag active" data-option="modelname">Checkpoint Name</div>
|
||||||
<div class="search-option-tag active" data-option="tags">Tags</div>
|
<div class="search-option-tag active" data-option="tags">Tags</div>
|
||||||
|
{% elif request.path == '/embeddings' %}
|
||||||
|
<div class="search-option-tag active" data-option="filename">Filename</div>
|
||||||
|
<div class="search-option-tag active" data-option="modelname">Embedding Name</div>
|
||||||
|
<div class="search-option-tag active" data-option="tags">Tags</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- Default options for LoRAs page -->
|
<!-- Default options for LoRAs page -->
|
||||||
<div class="search-option-tag active" data-option="filename">Filename</div>
|
<div class="search-option-tag active" data-option="filename">Filename</div>
|
||||||
@@ -147,6 +154,8 @@
|
|||||||
searchInput.placeholder = 'Search recipes...';
|
searchInput.placeholder = 'Search recipes...';
|
||||||
} else if (currentPath === '/checkpoints') {
|
} else if (currentPath === '/checkpoints') {
|
||||||
searchInput.placeholder = 'Search checkpoints...';
|
searchInput.placeholder = 'Search checkpoints...';
|
||||||
|
} else if (currentPath === '/embeddings') {
|
||||||
|
searchInput.placeholder = 'Search embeddings...';
|
||||||
} else {
|
} else {
|
||||||
searchInput.placeholder = 'Search...';
|
searchInput.placeholder = 'Search...';
|
||||||
}
|
}
|
||||||
@@ -156,6 +165,7 @@
|
|||||||
const lorasNavItem = document.getElementById('lorasNavItem');
|
const lorasNavItem = document.getElementById('lorasNavItem');
|
||||||
const recipesNavItem = document.getElementById('recipesNavItem');
|
const recipesNavItem = document.getElementById('recipesNavItem');
|
||||||
const checkpointsNavItem = document.getElementById('checkpointsNavItem');
|
const checkpointsNavItem = document.getElementById('checkpointsNavItem');
|
||||||
|
const embeddingsNavItem = document.getElementById('embeddingsNavItem');
|
||||||
const statisticsNavItem = document.getElementById('statisticsNavItem');
|
const statisticsNavItem = document.getElementById('statisticsNavItem');
|
||||||
|
|
||||||
if (currentPath === '/loras') {
|
if (currentPath === '/loras') {
|
||||||
@@ -164,6 +174,8 @@
|
|||||||
recipesNavItem.classList.add('active');
|
recipesNavItem.classList.add('active');
|
||||||
} else if (currentPath === '/checkpoints') {
|
} else if (currentPath === '/checkpoints') {
|
||||||
checkpointsNavItem.classList.add('active');
|
checkpointsNavItem.classList.add('active');
|
||||||
|
} else if (currentPath === '/embeddings') {
|
||||||
|
embeddingsNavItem.classList.add('active');
|
||||||
} else if (currentPath === '/statistics') {
|
} else if (currentPath === '/statistics') {
|
||||||
statisticsNavItem.classList.add('active');
|
statisticsNavItem.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user