mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
feat(metadata): enhance metadata archive management with download progress and status updates
This commit is contained in:
@@ -300,7 +300,11 @@
|
|||||||
"downloadError": "Failed to download metadata archive database",
|
"downloadError": "Failed to download metadata archive database",
|
||||||
"removeSuccess": "Metadata archive database removed successfully",
|
"removeSuccess": "Metadata archive database removed successfully",
|
||||||
"removeError": "Failed to remove metadata archive database",
|
"removeError": "Failed to remove metadata archive database",
|
||||||
"removeConfirm": "Are you sure you want to remove the metadata archive database? This will delete the local database file and you'll need to download it again to use this feature."
|
"removeConfirm": "Are you sure you want to remove the metadata archive database? This will delete the local database file and you'll need to download it again to use this feature.",
|
||||||
|
"preparing": "Preparing download...",
|
||||||
|
"connecting": "Connecting to download server...",
|
||||||
|
"completed": "Completed",
|
||||||
|
"downloadComplete": "Download completed successfully"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loras": {
|
"loras": {
|
||||||
|
|||||||
@@ -711,13 +711,23 @@ class MiscRoutes:
|
|||||||
try:
|
try:
|
||||||
archive_manager = await get_metadata_archive_manager()
|
archive_manager = await get_metadata_archive_manager()
|
||||||
|
|
||||||
|
# Get the download_id from query parameters if provided
|
||||||
|
download_id = request.query.get('download_id')
|
||||||
|
|
||||||
# Progress callback to send updates via WebSocket
|
# Progress callback to send updates via WebSocket
|
||||||
def progress_callback(stage, message):
|
def progress_callback(stage, message):
|
||||||
asyncio.create_task(ws_manager.broadcast({
|
data = {
|
||||||
'stage': stage,
|
'stage': stage,
|
||||||
'message': message,
|
'message': message,
|
||||||
'type': 'metadata_archive_download'
|
'type': 'metadata_archive_download'
|
||||||
}))
|
}
|
||||||
|
|
||||||
|
if download_id:
|
||||||
|
# Send to specific download WebSocket if download_id is provided
|
||||||
|
asyncio.create_task(ws_manager.broadcast_download_progress(download_id, data))
|
||||||
|
else:
|
||||||
|
# Fallback to general broadcast
|
||||||
|
asyncio.create_task(ws_manager.broadcast(data))
|
||||||
|
|
||||||
# Download and extract in background
|
# Download and extract in background
|
||||||
success = await archive_manager.download_and_extract_database(progress_callback)
|
success = await archive_manager.download_and_extract_database(progress_callback)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class MetadataArchiveManager:
|
|||||||
# Custom progress callback to report download progress
|
# Custom progress callback to report download progress
|
||||||
async def download_progress(progress):
|
async def download_progress(progress):
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
progress_callback("download", f"Downloaded {progress:.1f}%")
|
progress_callback("download", f"Downloading archive... {progress:.1f}%")
|
||||||
|
|
||||||
success, result = await downloader.download_file(
|
success, result = await downloader.download_file(
|
||||||
url=url,
|
url=url,
|
||||||
|
|||||||
@@ -208,6 +208,14 @@ body.modal-open {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled,
|
||||||
|
.primary-btn:disabled,
|
||||||
|
.danger-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.restart-required-icon {
|
.restart-required-icon {
|
||||||
color: var(--lora-warning);
|
color: var(--lora-warning);
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
@@ -228,14 +236,76 @@ body.modal-open {
|
|||||||
background-color: oklch(35% 0.02 256 / 0.98);
|
background-color: oklch(35% 0.02 256 / 0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-btn.disabled {
|
/* Danger button styles */
|
||||||
opacity: 0.5;
|
.danger-btn {
|
||||||
cursor: not-allowed;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: var(--lora-error);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
font-size: 0.95em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-btn.disabled {
|
.danger-btn:hover {
|
||||||
opacity: 0.5;
|
background-color: oklch(from var(--lora-error) l c h / 85%);
|
||||||
cursor: not-allowed;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Metadata archive status styles */
|
||||||
|
.metadata-archive-status {
|
||||||
|
background: rgba(0, 0, 0, 0.03);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
padding: var(--space-2);
|
||||||
|
margin-bottom: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .metadata-archive-status {
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid var(--lora-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-color);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-value {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-value.status-available {
|
||||||
|
color: var(--lora-success, #10b981);
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-value.status-unavailable {
|
||||||
|
color: var(--lora-warning, #f59e0b);
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-value.status-enabled {
|
||||||
|
color: var(--lora-success, #10b981);
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-status-value.status-disabled {
|
||||||
|
color: var(--lora-error, #ef4444);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add styles for delete preview image */
|
/* Add styles for delete preview image */
|
||||||
|
|||||||
@@ -789,6 +789,8 @@ export class SettingsManager {
|
|||||||
state.global.settings.compactMode = value;
|
state.global.settings.compactMode = value;
|
||||||
} else if (settingKey === 'include_trigger_words') {
|
} else if (settingKey === 'include_trigger_words') {
|
||||||
state.global.settings.includeTriggerWords = value;
|
state.global.settings.includeTriggerWords = value;
|
||||||
|
} else if (settingKey === 'enable_metadata_archive_db') {
|
||||||
|
state.global.settings.enable_metadata_archive_db = value;
|
||||||
} else {
|
} else {
|
||||||
// For any other settings that might be added in the future
|
// For any other settings that might be added in the future
|
||||||
state.global.settings[settingKey] = value;
|
state.global.settings[settingKey] = value;
|
||||||
@@ -799,7 +801,7 @@ export class SettingsManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// For backend settings, make API call
|
// For backend settings, make API call
|
||||||
if (['show_only_sfw'].includes(settingKey)) {
|
if (['show_only_sfw', 'enable_metadata_archive_db'].includes(settingKey)) {
|
||||||
const payload = {};
|
const payload = {};
|
||||||
payload[settingKey] = value;
|
payload[settingKey] = value;
|
||||||
|
|
||||||
@@ -814,6 +816,11 @@ export class SettingsManager {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Failed to save setting');
|
throw new Error('Failed to save setting');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Refresh metadata archive status when enable setting changes
|
||||||
|
if (settingKey === 'enable_metadata_archive_db') {
|
||||||
|
await this.updateMetadataArchiveStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
|
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
|
||||||
@@ -872,6 +879,8 @@ export class SettingsManager {
|
|||||||
state.global.settings.compactMode = (value !== 'default');
|
state.global.settings.compactMode = (value !== 'default');
|
||||||
} else if (settingKey === 'card_info_display') {
|
} else if (settingKey === 'card_info_display') {
|
||||||
state.global.settings.cardInfoDisplay = value;
|
state.global.settings.cardInfoDisplay = value;
|
||||||
|
} else if (settingKey === 'metadata_provider_priority') {
|
||||||
|
state.global.settings.metadata_provider_priority = value;
|
||||||
} else {
|
} else {
|
||||||
// For any other settings that might be added in the future
|
// For any other settings that might be added in the future
|
||||||
state.global.settings[settingKey] = value;
|
state.global.settings[settingKey] = value;
|
||||||
@@ -882,7 +891,7 @@ export class SettingsManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// For backend settings, make API call
|
// For backend settings, make API call
|
||||||
if (settingKey === 'default_lora_root' || settingKey === 'default_checkpoint_root' || settingKey === 'default_embedding_root' || settingKey === 'download_path_templates') {
|
if (settingKey === 'default_lora_root' || settingKey === 'default_checkpoint_root' || settingKey === 'default_embedding_root' || settingKey === 'download_path_templates' || settingKey === 'metadata_provider_priority') {
|
||||||
const payload = {};
|
const payload = {};
|
||||||
if (settingKey === 'download_path_templates') {
|
if (settingKey === 'download_path_templates') {
|
||||||
payload[settingKey] = state.global.settings.download_path_templates;
|
payload[settingKey] = state.global.settings.download_path_templates;
|
||||||
@@ -903,6 +912,11 @@ export class SettingsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
|
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
|
||||||
|
|
||||||
|
// Refresh metadata archive status when provider priority changes
|
||||||
|
if (settingKey === 'metadata_provider_priority') {
|
||||||
|
await this.updateMetadataArchiveStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply frontend settings immediately
|
// Apply frontend settings immediately
|
||||||
@@ -960,24 +974,24 @@ export class SettingsManager {
|
|||||||
const sizeText = status.databaseSize > 0 ? ` (${this.formatFileSize(status.databaseSize)})` : '';
|
const sizeText = status.databaseSize > 0 ? ` (${this.formatFileSize(status.databaseSize)})` : '';
|
||||||
|
|
||||||
statusContainer.innerHTML = `
|
statusContainer.innerHTML = `
|
||||||
<div class="status-info">
|
<div class="archive-status-item">
|
||||||
<div class="status-item">
|
<span class="archive-status-label">${translate('settings.metadataArchive.status')}:</span>
|
||||||
<strong>${translate('settings.metadataArchive.status')}:</strong>
|
<span class="archive-status-value status-${status.isAvailable ? 'available' : 'unavailable'}">
|
||||||
<span class="status-badge ${status.isAvailable ? 'status-available' : 'status-unavailable'}">
|
${status.isAvailable ? translate('settings.metadataArchive.statusAvailable') : translate('settings.metadataArchive.statusUnavailable')}
|
||||||
${status.isAvailable ? translate('settings.metadataArchive.statusAvailable') : translate('settings.metadataArchive.statusUnavailable')}
|
|
||||||
</span>
|
|
||||||
${sizeText}
|
${sizeText}
|
||||||
</div>
|
</span>
|
||||||
<div class="status-item">
|
</div>
|
||||||
<strong>${translate('settings.metadataArchive.enabled')}:</strong>
|
<div class="archive-status-item">
|
||||||
<span class="status-badge ${status.isEnabled ? 'status-enabled' : 'status-disabled'}">
|
<span class="archive-status-label">${translate('settings.metadataArchive.enabled')}:</span>
|
||||||
${status.isEnabled ? translate('common.enabled') : translate('common.disabled')}
|
<span class="archive-status-value status-${status.isEnabled ? 'enabled' : 'disabled'}">
|
||||||
</span>
|
${status.isEnabled ? translate('common.status.enabled') : translate('common.status.disabled')}
|
||||||
</div>
|
</span>
|
||||||
<div class="status-item">
|
</div>
|
||||||
<strong>${translate('settings.metadataArchive.currentPriority')}:</strong>
|
<div class="archive-status-item">
|
||||||
|
<span class="archive-status-label">${translate('settings.metadataArchive.currentPriority')}:</span>
|
||||||
|
<span class="archive-status-value">
|
||||||
${status.priority === 'archive_db' ? translate('settings.metadataArchive.priorityArchiveDb') : translate('settings.metadataArchive.priorityCivitaiApi')}
|
${status.priority === 'archive_db' ? translate('settings.metadataArchive.priorityArchiveDb') : translate('settings.metadataArchive.priorityCivitaiApi')}
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -1012,12 +1026,81 @@ export class SettingsManager {
|
|||||||
async downloadMetadataArchive() {
|
async downloadMetadataArchive() {
|
||||||
try {
|
try {
|
||||||
const downloadBtn = document.getElementById('downloadMetadataArchiveBtn');
|
const downloadBtn = document.getElementById('downloadMetadataArchiveBtn');
|
||||||
|
|
||||||
if (downloadBtn) {
|
if (downloadBtn) {
|
||||||
downloadBtn.disabled = true;
|
downloadBtn.disabled = true;
|
||||||
downloadBtn.textContent = translate('settings.metadataArchive.downloadingButton');
|
downloadBtn.textContent = translate('settings.metadataArchive.downloadingButton');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show loading with enhanced progress
|
||||||
|
const progressUpdater = state.loadingManager.showEnhancedProgress(translate('settings.metadataArchive.preparing'));
|
||||||
|
|
||||||
const response = await fetch('/api/download-metadata-archive', {
|
// Set up WebSocket for progress updates
|
||||||
|
const wsProtocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||||
|
const downloadId = `metadata_archive_${Date.now()}`;
|
||||||
|
const ws = new WebSocket(`${wsProtocol}${window.location.host}/ws/download-progress?id=${downloadId}`);
|
||||||
|
|
||||||
|
let wsConnected = false;
|
||||||
|
let actualDownloadId = downloadId; // Will be updated when WebSocket confirms the ID
|
||||||
|
|
||||||
|
// Promise to wait for WebSocket connection and ID confirmation
|
||||||
|
const wsReady = new Promise((resolve) => {
|
||||||
|
ws.onopen = () => {
|
||||||
|
wsConnected = true;
|
||||||
|
console.log('Connected to metadata archive download progress WebSocket');
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onmessage = (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
|
||||||
|
// Handle download ID confirmation
|
||||||
|
if (data.type === 'download_id') {
|
||||||
|
actualDownloadId = data.download_id;
|
||||||
|
console.log(`Connected to metadata archive download progress with ID: ${data.download_id}`);
|
||||||
|
resolve(data.download_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle metadata archive download progress
|
||||||
|
if (data.type === 'metadata_archive_download') {
|
||||||
|
const message = data.message || '';
|
||||||
|
|
||||||
|
// Update progress bar based on stage
|
||||||
|
let progressPercent = 0;
|
||||||
|
if (data.stage === 'download') {
|
||||||
|
// Extract percentage from message if available
|
||||||
|
const percentMatch = data.message.match(/(\d+\.?\d*)%/);
|
||||||
|
if (percentMatch) {
|
||||||
|
progressPercent = Math.min(parseFloat(percentMatch[1]), 90); // Cap at 90% for download
|
||||||
|
} else {
|
||||||
|
progressPercent = 0; // Default download progress
|
||||||
|
}
|
||||||
|
} else if (data.stage === 'extract') {
|
||||||
|
progressPercent = 95; // Near completion for extraction
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update loading manager progress
|
||||||
|
progressUpdater.updateProgress(progressPercent, '', `${message}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onerror = (error) => {
|
||||||
|
console.error('WebSocket error:', error);
|
||||||
|
resolve(downloadId); // Fallback to original ID
|
||||||
|
};
|
||||||
|
|
||||||
|
// Timeout fallback
|
||||||
|
setTimeout(() => resolve(downloadId), 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
console.log('WebSocket connection closed');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wait for WebSocket to be ready
|
||||||
|
await wsReady;
|
||||||
|
|
||||||
|
const response = await fetch(`/api/download-metadata-archive?download_id=${encodeURIComponent(actualDownloadId)}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -1026,8 +1109,16 @@ export class SettingsManager {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Close WebSocket
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
showNotification(translate('settings.metadataArchive.downloadSuccess'), 'success');
|
// Complete progress
|
||||||
|
await progressUpdater.complete(translate('settings.metadataArchive.downloadComplete'));
|
||||||
|
|
||||||
|
showToast('settings.metadataArchive.downloadSuccess', 'success');
|
||||||
|
|
||||||
// Update settings in state
|
// Update settings in state
|
||||||
state.global.settings.enable_metadata_archive_db = true;
|
state.global.settings.enable_metadata_archive_db = true;
|
||||||
@@ -1041,11 +1132,17 @@ export class SettingsManager {
|
|||||||
|
|
||||||
await this.updateMetadataArchiveStatus();
|
await this.updateMetadataArchiveStatus();
|
||||||
} else {
|
} else {
|
||||||
showNotification(translate('settings.metadataArchive.downloadError') + ': ' + data.error, 'error');
|
// Hide loading on error
|
||||||
|
state.loadingManager.hide();
|
||||||
|
showToast('settings.metadataArchive.downloadError' + ': ' + data.error, 'error');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error downloading metadata archive:', error);
|
console.error('Error downloading metadata archive:', error);
|
||||||
showNotification(translate('settings.metadataArchive.downloadError') + ': ' + error.message, 'error');
|
|
||||||
|
// Hide loading on error
|
||||||
|
state.loadingManager.hide();
|
||||||
|
|
||||||
|
showToast('settings.metadataArchive.downloadError' + ': ' + error.message, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
const downloadBtn = document.getElementById('downloadMetadataArchiveBtn');
|
const downloadBtn = document.getElementById('downloadMetadataArchiveBtn');
|
||||||
if (downloadBtn) {
|
if (downloadBtn) {
|
||||||
@@ -1077,8 +1174,8 @@ export class SettingsManager {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
showNotification(translate('settings.metadataArchive.removeSuccess'), 'success');
|
showToast('settings.metadataArchive.removeSuccess', 'success');
|
||||||
|
|
||||||
// Update settings in state
|
// Update settings in state
|
||||||
state.global.settings.enable_metadata_archive_db = false;
|
state.global.settings.enable_metadata_archive_db = false;
|
||||||
setStorageItem('settings', state.global.settings);
|
setStorageItem('settings', state.global.settings);
|
||||||
@@ -1091,11 +1188,11 @@ export class SettingsManager {
|
|||||||
|
|
||||||
await this.updateMetadataArchiveStatus();
|
await this.updateMetadataArchiveStatus();
|
||||||
} else {
|
} else {
|
||||||
showNotification(translate('settings.metadataArchive.removeError') + ': ' + data.error, 'error');
|
showToast('settings.metadataArchive.removeError' + ': ' + data.error, 'error');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error removing metadata archive:', error);
|
console.error('Error removing metadata archive:', error);
|
||||||
showNotification(translate('settings.metadataArchive.removeError') + ': ' + error.message, 'error');
|
showToast('settings.metadataArchive.removeError' + ': ' + error.message, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
const removeBtn = document.getElementById('removeMetadataArchiveBtn');
|
const removeBtn = document.getElementById('removeMetadataArchiveBtn');
|
||||||
if (removeBtn) {
|
if (removeBtn) {
|
||||||
|
|||||||
@@ -398,28 +398,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Misc. Section -->
|
|
||||||
<div class="settings-section">
|
|
||||||
<h3>{{ t('settings.sections.misc') }}</h3>
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="includeTriggerWords">{{ t('settings.misc.includeTriggerWords') }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control">
|
|
||||||
<label class="toggle-switch">
|
|
||||||
<input type="checkbox" id="includeTriggerWords"
|
|
||||||
onchange="settingsManager.saveToggleSetting('includeTriggerWords', 'include_trigger_words')">
|
|
||||||
<span class="toggle-slider"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="input-help">
|
|
||||||
{{ t('settings.misc.includeTriggerWordsHelp') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Metadata Archive Section -->
|
<!-- Metadata Archive Section -->
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<h3>{{ t('settings.sections.metadataArchive') }}</h3>
|
<h3>{{ t('settings.sections.metadataArchive') }}</h3>
|
||||||
@@ -470,10 +448,10 @@
|
|||||||
<label>{{ t('settings.metadataArchive.management') }}:</label>
|
<label>{{ t('settings.metadataArchive.management') }}:</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-control">
|
<div class="setting-control">
|
||||||
<button type="button" id="downloadMetadataArchiveBtn" class="btn btn-primary" onclick="settingsManager.downloadMetadataArchive()">
|
<button type="button" id="downloadMetadataArchiveBtn" class="primary-btn" onclick="settingsManager.downloadMetadataArchive()">
|
||||||
{{ t('settings.metadataArchive.downloadButton') }}
|
{{ t('settings.metadataArchive.downloadButton') }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="removeMetadataArchiveBtn" class="btn btn-danger" onclick="settingsManager.removeMetadataArchive()" style="margin-left: 10px;">
|
<button type="button" id="removeMetadataArchiveBtn" class="danger-btn" onclick="settingsManager.removeMetadataArchive()" style="margin-left: 10px;">
|
||||||
{{ t('settings.metadataArchive.removeButton') }}
|
{{ t('settings.metadataArchive.removeButton') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -483,6 +461,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Misc. Section -->
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>{{ t('settings.sections.misc') }}</h3>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-row">
|
||||||
|
<div class="setting-info">
|
||||||
|
<label for="includeTriggerWords">{{ t('settings.misc.includeTriggerWords') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<label class="toggle-switch">
|
||||||
|
<input type="checkbox" id="includeTriggerWords"
|
||||||
|
onchange="settingsManager.saveToggleSetting('includeTriggerWords', 'include_trigger_words')">
|
||||||
|
<span class="toggle-slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-help">
|
||||||
|
{{ t('settings.misc.includeTriggerWordsHelp') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user