refactor: rename 'lora-card' to 'model-card' across styles and scripts for consistency

This commit is contained in:
Will Miao
2025-07-25 23:23:57 +08:00
parent e4ce384023
commit 381bd3938a
21 changed files with 58 additions and 60 deletions

View File

@@ -73,12 +73,12 @@
} }
/* Style for selected cards */ /* Style for selected cards */
.lora-card.selected { .model-card.selected {
box-shadow: 0 0 0 2px var(--lora-accent); box-shadow: 0 0 0 2px var(--lora-accent);
position: relative; position: relative;
} }
.lora-card.selected::after { .model-card.selected::after {
content: "✓"; content: "✓";
position: absolute; position: absolute;
top: 10px; top: 10px;

View File

@@ -14,7 +14,7 @@
box-sizing: border-box; /* Include padding in width calculation */ box-sizing: border-box; /* Include padding in width calculation */
} }
.lora-card { .model-card {
background: var(--lora-surface); background: var(--lora-surface);
border: 1px solid var(--lora-border); border: 1px solid var(--lora-border);
border-radius: var(--border-radius-base); border-radius: var(--border-radius-base);
@@ -30,12 +30,12 @@
overflow: hidden; overflow: hidden;
} }
.lora-card:hover { .model-card:hover {
transform: translateY(-2px); transform: translateY(-2px);
background: oklch(100% 0 0 / 0.6); background: oklch(100% 0 0 / 0.6);
} }
.lora-card:focus-visible { .model-card:focus-visible {
outline: 2px solid var(--lora-accent); outline: 2px solid var(--lora-accent);
outline-offset: 2px; outline-offset: 2px;
} }
@@ -47,7 +47,7 @@
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
} }
.lora-card { .model-card {
max-width: 270px; max-width: 270px;
} }
} }
@@ -59,7 +59,7 @@
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
} }
.lora-card { .model-card {
max-width: 280px; max-width: 280px;
} }
} }
@@ -70,7 +70,7 @@
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
} }
.lora-card { .model-card {
max-width: 240px; max-width: 240px;
} }
} }
@@ -259,8 +259,8 @@
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
} }
.hover-reveal .lora-card:hover .card-header, .hover-reveal .model-card:hover .card-header,
.hover-reveal .lora-card:hover .card-footer { .hover-reveal .model-card:hover .card-footer {
opacity: 1; opacity: 1;
} }
@@ -345,7 +345,7 @@
grid-template-columns: minmax(260px, 1fr); /* Adjusted minimum size for mobile */ grid-template-columns: minmax(260px, 1fr); /* Adjusted minimum size for mobile */
} }
.lora-card { .model-card {
max-width: 100%; /* Allow cards to fill available space on mobile */ max-width: 100%; /* Allow cards to fill available space on mobile */
} }
} }
@@ -425,8 +425,8 @@
} }
/* Prevent text selection on cards and interactive elements */ /* Prevent text selection on cards and interactive elements */
.lora-card, .model-card,
.lora-card *, .model-card *,
.card-actions, .card-actions,
.card-actions i, .card-actions i,
.toggle-blur-btn, .toggle-blur-btn,
@@ -510,7 +510,7 @@
} }
} }
/* Add after the existing .lora-card:hover styles */ /* Add after the existing .model-card:hover styles */
@keyframes update-pulse { @keyframes update-pulse {
0% { box-shadow: 0 0 0 0 var(--lora-accent-transparent); } 0% { box-shadow: 0 0 0 0 var(--lora-accent-transparent); }
@@ -523,7 +523,7 @@
--lora-accent-transparent: oklch(var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h) / 0.6); --lora-accent-transparent: oklch(var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h) / 0.6);
} }
.lora-card.updated { .model-card.updated {
animation: update-pulse 1.2s ease-out; animation: update-pulse 1.2s ease-out;
} }

View File

@@ -195,7 +195,7 @@
} }
/* Make cards in duplicate groups have consistent width */ /* Make cards in duplicate groups have consistent width */
.card-group-container .lora-card { .card-group-container .model-card {
flex: 0 0 auto; flex: 0 0 auto;
width: 240px; width: 240px;
margin: 0; margin: 0;
@@ -241,26 +241,26 @@
} }
/* Duplicate card styling */ /* Duplicate card styling */
.lora-card.duplicate { .model-card.duplicate {
position: relative; position: relative;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.lora-card.duplicate:hover { .model-card.duplicate:hover {
border-color: var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h); border-color: var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h);
} }
.lora-card.duplicate.latest { .model-card.duplicate.latest {
border-style: solid; border-style: solid;
border-color: oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h)); border-color: oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h));
} }
.lora-card.duplicate-selected { .model-card.duplicate-selected {
border: 2px solid oklch(var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h)); border: 2px solid oklch(var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h));
box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
} }
.lora-card .selector-checkbox { .model-card .selector-checkbox {
position: absolute; position: absolute;
top: 10px; top: 10px;
right: 10px; right: 10px;
@@ -271,7 +271,7 @@
} }
/* Latest indicator */ /* Latest indicator */
.lora-card.duplicate.latest::after { .model-card.duplicate.latest::after {
content: "Latest"; content: "Latest";
position: absolute; position: absolute;
top: 10px; top: 10px;
@@ -365,13 +365,13 @@
} }
/* Hash Mismatch Styling */ /* Hash Mismatch Styling */
.lora-card.duplicate.hash-mismatch { .model-card.duplicate.hash-mismatch {
border: 2px dashed oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h)); border: 2px dashed oklch(var(--lora-warning-l) var(--lora-warning-c) var(--lora-warning-h));
opacity: 0.85; opacity: 0.85;
position: relative; position: relative;
} }
.lora-card.duplicate.hash-mismatch::before { .model-card.duplicate.hash-mismatch::before {
content: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
@@ -389,7 +389,7 @@
pointer-events: none; pointer-events: none;
} }
.lora-card.duplicate.hash-mismatch .card-preview { .model-card.duplicate.hash-mismatch .card-preview {
filter: grayscale(20%); filter: grayscale(20%);
} }
@@ -407,7 +407,7 @@
} }
/* Disabled checkbox style */ /* Disabled checkbox style */
.lora-card.duplicate.hash-mismatch .selector-checkbox { .model-card.duplicate.hash-mismatch .selector-checkbox {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }

View File

@@ -109,7 +109,7 @@
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.lora-card, .model-card,
.progress-bar, .progress-bar,
.current-item-bar { .current-item-bar {
transition: none; transition: none;

View File

@@ -6,7 +6,7 @@ import { showDeleteModal, showExcludeModal } from '../../utils/modalUtils.js';
export class CheckpointContextMenu extends BaseContextMenu { export class CheckpointContextMenu extends BaseContextMenu {
constructor() { constructor() {
super('checkpointContextMenu', '.lora-card'); super('checkpointContextMenu', '.model-card');
this.nsfwSelector = document.getElementById('nsfwLevelSelector'); this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'checkpoint'; this.modelType = 'checkpoint';
this.resetAndReload = resetAndReload; this.resetAndReload = resetAndReload;

View File

@@ -6,7 +6,7 @@ import { showDeleteModal, showExcludeModal } from '../../utils/modalUtils.js';
export class EmbeddingContextMenu extends BaseContextMenu { export class EmbeddingContextMenu extends BaseContextMenu {
constructor() { constructor() {
super('embeddingContextMenu', '.embedding-card'); super('embeddingContextMenu', '.model-card');
this.nsfwSelector = document.getElementById('nsfwLevelSelector'); this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'embedding'; this.modelType = 'embedding';
this.resetAndReload = resetAndReload; this.resetAndReload = resetAndReload;

View File

@@ -6,7 +6,7 @@ import { showExcludeModal, showDeleteModal } from '../../utils/modalUtils.js';
export class LoraContextMenu extends BaseContextMenu { export class LoraContextMenu extends BaseContextMenu {
constructor() { constructor() {
super('loraContextMenu', '.lora-card'); super('loraContextMenu', '.model-card');
this.nsfwSelector = document.getElementById('nsfwLevelSelector'); this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'lora'; this.modelType = 'lora';
this.resetAndReload = resetAndReload; this.resetAndReload = resetAndReload;

View File

@@ -7,7 +7,7 @@ import { state } from '../../state/index.js';
export class RecipeContextMenu extends BaseContextMenu { export class RecipeContextMenu extends BaseContextMenu {
constructor() { constructor() {
super('recipeContextMenu', '.lora-card'); super('recipeContextMenu', '.model-card');
this.nsfwSelector = document.getElementById('nsfwLevelSelector'); this.nsfwSelector = document.getElementById('nsfwLevelSelector');
this.modelType = 'recipe'; this.modelType = 'recipe';

View File

@@ -243,7 +243,7 @@ export class DuplicatesManager {
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
checkbox.checked = !allSelected; checkbox.checked = !allSelected;
const recipeId = checkbox.dataset.recipeId; const recipeId = checkbox.dataset.recipeId;
const card = checkbox.closest('.lora-card'); const card = checkbox.closest('.model-card');
if (!allSelected) { if (!allSelected) {
this.selectedForDeletion.add(recipeId); this.selectedForDeletion.add(recipeId);
@@ -268,7 +268,7 @@ export class DuplicatesManager {
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
checkbox.checked = true; checkbox.checked = true;
this.selectedForDeletion.add(checkbox.dataset.recipeId); this.selectedForDeletion.add(checkbox.dataset.recipeId);
checkbox.closest('.lora-card').classList.add('duplicate-selected'); checkbox.closest('.model-card').classList.add('duplicate-selected');
}); });
// Update the button text // Update the button text
@@ -299,7 +299,7 @@ export class DuplicatesManager {
if (checkbox) { if (checkbox) {
checkbox.checked = true; checkbox.checked = true;
this.selectedForDeletion.add(recipeId); this.selectedForDeletion.add(recipeId);
checkbox.closest('.lora-card').classList.add('duplicate-selected'); checkbox.closest('.model-card').classList.add('duplicate-selected');
} }
} }
@@ -310,7 +310,7 @@ export class DuplicatesManager {
if (latestCheckbox) { if (latestCheckbox) {
latestCheckbox.checked = false; latestCheckbox.checked = false;
this.selectedForDeletion.delete(latestId); this.selectedForDeletion.delete(latestId);
latestCheckbox.closest('.lora-card').classList.remove('duplicate-selected'); latestCheckbox.closest('.model-card').classList.remove('duplicate-selected');
} }
this.updateSelectedCount(); this.updateSelectedCount();

View File

@@ -330,7 +330,7 @@ export class ModelDuplicatesManager {
renderModelCard(model, groupHash) { renderModelCard(model, groupHash) {
// Create basic card structure // Create basic card structure
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'lora-card duplicate'; card.className = 'model-card duplicate';
card.dataset.hash = model.sha256; card.dataset.hash = model.sha256;
card.dataset.filePath = model.file_path; card.dataset.filePath = model.file_path;
@@ -549,7 +549,7 @@ export class ModelDuplicatesManager {
checkboxes.forEach(checkbox => { checkboxes.forEach(checkbox => {
checkbox.checked = !allSelected; checkbox.checked = !allSelected;
const filePath = checkbox.dataset.filePath; const filePath = checkbox.dataset.filePath;
const card = checkbox.closest('.lora-card'); const card = checkbox.closest('.model-card');
if (!allSelected) { if (!allSelected) {
this.selectedForDeletion.add(filePath); this.selectedForDeletion.add(filePath);

View File

@@ -17,7 +17,7 @@ class RecipeCard {
createCardElement() { createCardElement() {
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'lora-card'; card.className = 'model-card';
card.dataset.filepath = this.recipe.file_path; card.dataset.filepath = this.recipe.file_path;
card.dataset.title = this.recipe.title; card.dataset.title = this.recipe.title;
card.dataset.nsfwLevel = this.recipe.preview_nsfw_level || 0; card.dataset.nsfwLevel = this.recipe.preview_nsfw_level || 0;

View File

@@ -242,7 +242,7 @@ export class PageControls {
* @param {string} folderPath - Folder path to filter by * @param {string} folderPath - Folder path to filter by
*/ */
filterByFolder(folderPath) { filterByFolder(folderPath) {
const cardSelector = this.pageType === 'loras' ? '.lora-card' : '.checkpoint-card'; const cardSelector = this.pageType === 'loras' ? '.model-card' : '.checkpoint-card';
document.querySelectorAll(cardSelector).forEach(card => { document.querySelectorAll(cardSelector).forEach(card => {
card.style.display = card.dataset.folder === folderPath ? '' : 'none'; card.style.display = card.dataset.folder === folderPath ? '' : 'none';
}); });
@@ -374,7 +374,7 @@ export class PageControls {
openCivitai(modelName) { openCivitai(modelName) {
// Get card selector based on page type // Get card selector based on page type
const cardSelector = this.pageType === 'loras' const cardSelector = this.pageType === 'loras'
? `.lora-card[data-name="${modelName}"]` ? `.model-card[data-name="${modelName}"]`
: `.checkpoint-card[data-name="${modelName}"]`; : `.checkpoint-card[data-name="${modelName}"]`;
const card = document.querySelector(cardSelector); const card = document.querySelector(cardSelector);

View File

@@ -28,10 +28,8 @@ export function setupModelCardEventDelegation(modelType) {
// Event delegation handler for all model card events // Event delegation handler for all model card events
function handleModelCardEvent_internal(event, modelType) { function handleModelCardEvent_internal(event, modelType) {
// Find the closest card element // Find the closest card element
const card = event.target.closest('.lora-card'); const card = event.target.closest('.model-card');
if (!card) return; if (!card) return;
const apiClient = getModelApiClient();
// Handle specific elements within the card // Handle specific elements within the card
if (event.target.closest('.toggle-blur-btn')) { if (event.target.closest('.toggle-blur-btn')) {
@@ -80,7 +78,7 @@ function handleModelCardEvent_internal(event, modelType) {
if (event.target.closest('.fa-image')) { if (event.target.closest('.fa-image')) {
event.stopPropagation(); event.stopPropagation();
apiClient.replaceModelPreview(card.dataset.filepath); getModelApiClient().replaceModelPreview(card.dataset.filepath);
return; return;
} }
@@ -137,7 +135,7 @@ async function toggleFavorite(card) {
const newFavoriteState = !isFavorite; const newFavoriteState = !isFavorite;
try { try {
await apiClient.saveModelMetadata(card.dataset.filepath, { await getModelApiClient().saveModelMetadata(card.dataset.filepath, {
favorite: newFavoriteState favorite: newFavoriteState
}); });
@@ -364,7 +362,7 @@ function showExampleAccessModal(card, modelType) {
export function createModelCard(model, modelType) { export function createModelCard(model, modelType) {
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'lora-card'; // Reuse the same class for styling card.className = 'model-card'; // Reuse the same class for styling
card.dataset.sha256 = model.sha256; card.dataset.sha256 = model.sha256;
card.dataset.filepath = model.file_path; card.dataset.filepath = model.file_path;
card.dataset.name = model.model_name; card.dataset.name = model.model_name;
@@ -518,7 +516,7 @@ export function updateCardsForBulkMode(isBulkMode) {
document.body.classList.toggle('bulk-mode', isBulkMode); document.body.classList.toggle('bulk-mode', isBulkMode);
// Get all lora cards - this can now be from the DOM or through the virtual scroller // Get all lora cards - this can now be from the DOM or through the virtual scroller
const loraCards = document.querySelectorAll('.lora-card'); const loraCards = document.querySelectorAll('.model-card');
loraCards.forEach(card => { loraCards.forEach(card => {
// Get all action containers for this card // Get all action containers for this card

View File

@@ -380,7 +380,7 @@ function setupLoraSpecificFields(filePath) {
if (!key || !value) return; if (!key || !value) return;
const loraCard = document.querySelector(`.lora-card[data-filepath="${filePath}"]`); const loraCard = document.querySelector(`.model-card[data-filepath="${filePath}"]`);
const currentPresets = parsePresets(loraCard?.dataset.usage_tips); const currentPresets = parsePresets(loraCard?.dataset.usage_tips);
currentPresets[key] = parseFloat(value); currentPresets[key] = parseFloat(value);

View File

@@ -52,7 +52,7 @@ window.removePreset = async function(key) {
.querySelector('.file-path').textContent + .querySelector('.file-path').textContent +
document.querySelector('#modelModal .modal-content') document.querySelector('#modelModal .modal-content')
.querySelector('#file-name').textContent + '.safetensors'; .querySelector('#file-name').textContent + '.safetensors';
const loraCard = document.querySelector(`.lora-card[data-filepath="${filePath}"]`); const loraCard = document.querySelector(`.model-card[data-filepath="${filePath}"]`);
const currentPresets = parsePresets(loraCard.dataset.usage_tips); const currentPresets = parsePresets(loraCard.dataset.usage_tips);
delete currentPresets[key]; delete currentPresets[key];

View File

@@ -96,7 +96,7 @@ function renderRecipes(tabElement, recipes, loraName, loraHash) {
// Create card element matching the structure in recipes.html // Create card element matching the structure in recipes.html
const card = document.createElement('div'); const card = document.createElement('div');
card.className = 'lora-card'; card.className = 'model-card';
card.dataset.filePath = recipe.file_path || ''; card.dataset.filePath = recipe.file_path || '';
card.dataset.title = recipe.title || ''; card.dataset.title = recipe.title || '';
card.dataset.created = recipe.created_date || ''; card.dataset.created = recipe.created_date || '';

View File

@@ -105,7 +105,7 @@ export class BulkManager {
// TODO: fix this, no DOM manipulation should be done here // TODO: fix this, no DOM manipulation should be done here
// Force a lightweight refresh of the cards to ensure proper display // Force a lightweight refresh of the cards to ensure proper display
// This is less disruptive than a full resetAndReload() // This is less disruptive than a full resetAndReload()
document.querySelectorAll('.lora-card').forEach(card => { document.querySelectorAll('.model-card').forEach(card => {
// Re-apply normal display mode to all card actions // Re-apply normal display mode to all card actions
const actions = card.querySelectorAll('.card-actions, .card-button'); const actions = card.querySelectorAll('.card-actions, .card-button');
actions.forEach(action => action.style.display = 'flex'); actions.forEach(action => action.style.display = 'flex');
@@ -114,7 +114,7 @@ export class BulkManager {
} }
clearSelection() { clearSelection() {
document.querySelectorAll('.lora-card.selected').forEach(card => { document.querySelectorAll('.model-card.selected').forEach(card => {
card.classList.remove('selected'); card.classList.remove('selected');
}); });
state.selectedLoras.clear(); state.selectedLoras.clear();
@@ -190,7 +190,7 @@ export class BulkManager {
applySelectionState() { applySelectionState() {
if (!state.bulkMode) return; if (!state.bulkMode) return;
document.querySelectorAll('.lora-card').forEach(card => { document.querySelectorAll('.model-card').forEach(card => {
const filepath = card.dataset.filepath; const filepath = card.dataset.filepath;
if (state.selectedLoras.has(filepath)) { if (state.selectedLoras.has(filepath)) {
card.classList.add('selected'); card.classList.add('selected');
@@ -502,7 +502,7 @@ export class BulkManager {
deselectItem(filepath) { deselectItem(filepath) {
// Find and deselect the corresponding card if it's in the DOM // Find and deselect the corresponding card if it's in the DOM
const card = document.querySelector(`.lora-card[data-filepath="${filepath}"]`); const card = document.querySelector(`.model-card[data-filepath="${filepath}"]`);
if (card) { if (card) {
card.classList.remove('selected'); card.classList.remove('selected');
} }

View File

@@ -734,7 +734,7 @@ export class SettingsManager {
applyFrontendSettings() { applyFrontendSettings() {
// Apply blur setting to existing content // Apply blur setting to existing content
const blurSetting = state.global.settings.blurMatureContent; const blurSetting = state.global.settings.blurMatureContent;
document.querySelectorAll('.lora-card[data-nsfw="true"] .card-image').forEach(img => { document.querySelectorAll('.model-card[data-nsfw="true"] .card-image').forEach(img => {
if (blurSetting) { if (blurSetting) {
img.classList.add('nsfw-blur'); img.classList.add('nsfw-blur');
} else { } else {

View File

@@ -9,7 +9,7 @@
*/ */
export function updateRecipeCard(recipeId, updates) { export function updateRecipeCard(recipeId, updates) {
// Find the card with matching recipe ID // Find the card with matching recipe ID
const recipeCard = document.querySelector(`.lora-card[data-id="${recipeId}"]`); const recipeCard = document.querySelector(`.model-card[data-id="${recipeId}"]`);
if (!recipeCard) return; if (!recipeCard) return;
// Get the recipe card component instance // Get the recipe card component instance

View File

@@ -9,7 +9,7 @@ let pendingExcludePath = null;
export function showDeleteModal(filePath) { export function showDeleteModal(filePath) {
pendingDeletePath = filePath; pendingDeletePath = filePath;
const card = document.querySelector(`.lora-card[data-filepath="${filePath}"]`); const card = document.querySelector(`.model-card[data-filepath="${filePath}"]`);
const modelName = card ? card.dataset.name : filePath.split('/').pop(); const modelName = card ? card.dataset.name : filePath.split('/').pop();
const modal = modalManager.getModal('deleteModal').element; const modal = modalManager.getModal('deleteModal').element;
const modelInfo = modal.querySelector('.delete-model-info'); const modelInfo = modal.querySelector('.delete-model-info');
@@ -49,7 +49,7 @@ export function closeDeleteModal() {
export function showExcludeModal(filePath) { export function showExcludeModal(filePath) {
pendingExcludePath = filePath; pendingExcludePath = filePath;
const card = document.querySelector(`.lora-card[data-filepath="${filePath}"]`); const card = document.querySelector(`.model-card[data-filepath="${filePath}"]`);
const modelName = card ? card.dataset.name : filePath.split('/').pop(); const modelName = card ? card.dataset.name : filePath.split('/').pop();
const modal = modalManager.getModal('excludeModal').element; const modal = modalManager.getModal('excludeModal').element;
const modelInfo = modal.querySelector('.exclude-model-info'); const modelInfo = modal.querySelector('.exclude-model-info');

View File

@@ -168,13 +168,13 @@ function updateThemeToggleIcons(theme) {
} }
function filterByFolder(folderPath) { function filterByFolder(folderPath) {
document.querySelectorAll('.lora-card').forEach(card => { document.querySelectorAll('.model-card').forEach(card => {
card.style.display = card.dataset.folder === folderPath ? '' : 'none'; card.style.display = card.dataset.folder === folderPath ? '' : 'none';
}); });
} }
export function openCivitai(filePath) { export function openCivitai(filePath) {
const loraCard = document.querySelector(`.lora-card[data-filepath="${filePath}"]`); const loraCard = document.querySelector(`.model-card[data-filepath="${filePath}"]`);
if (!loraCard) return; if (!loraCard) return;
const metaData = JSON.parse(loraCard.dataset.meta); const metaData = JSON.parse(loraCard.dataset.meta);