| |
| |
| |
|
|
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const settingsForm = document.getElementById('settings-form'); |
| const downloadModelForm = document.getElementById('download-model-form'); |
| const cloneModelForm = document.getElementById('clone-model-form'); |
| const advancedSettingsEditor = document.getElementById('advanced-settings'); |
| |
| |
| if (settingsForm) { |
| initializeSettingsPage(); |
| } |
| |
| |
| |
| |
| function initializeSettingsPage() { |
| |
| if (advancedSettingsEditor) { |
| try { |
| const currentSettings = advancedSettingsEditor.value; |
| if (currentSettings) { |
| const formattedSettings = JSON.stringify(JSON.parse(currentSettings), null, 2); |
| advancedSettingsEditor.value = formattedSettings; |
| } |
| } catch (e) { |
| console.error('Error formatting advanced settings JSON:', e); |
| } |
| } |
| |
| |
| if (downloadModelForm) { |
| downloadModelForm.addEventListener('submit', function(e) { |
| e.preventDefault(); |
| downloadModel(); |
| }); |
| } |
| |
| |
| if (cloneModelForm) { |
| cloneModelForm.addEventListener('submit', function(e) { |
| e.preventDefault(); |
| cloneModel(); |
| }); |
| } |
| |
| |
| loadAvailableModels(); |
| } |
| |
| |
| |
| |
| function downloadModel() { |
| const modelName = document.getElementById('model-name').value; |
| const modelSource = document.getElementById('model-source').value; |
| |
| |
| let repoUrl, githubBranch, githubToken, hfToken; |
| |
| if (modelSource === 'github') { |
| repoUrl = document.getElementById('repo-url')?.value; |
| githubBranch = document.getElementById('github-branch')?.value; |
| githubToken = document.getElementById('github-token')?.value; |
| } else { |
| hfToken = document.getElementById('hf-token')?.value; |
| } |
| |
| |
| if (!modelName) { |
| showAlert('Please enter a model name.', 'danger'); |
| return; |
| } |
| |
| if (modelSource === 'github' && !repoUrl) { |
| showAlert('Please enter a GitHub repository URL.', 'danger'); |
| return; |
| } |
| |
| |
| toggleFormElements(downloadModelForm, true); |
| |
| |
| showAlert('Starting model download. This may take a while...', 'info', 'download-status'); |
| |
| |
| const data = { |
| model_name: modelName, |
| source: modelSource |
| }; |
| |
| |
| if (modelSource === 'github') { |
| data.repo_url = repoUrl; |
| if (githubBranch) data.branch = githubBranch; |
| if (githubToken) data.github_token = githubToken; |
| } else if (modelSource === 'huggingface') { |
| if (hfToken) data.hf_token = hfToken; |
| } |
| |
| |
| fetch('/api/models/download', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify(data), |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| toggleFormElements(downloadModelForm, false); |
| |
| if (data.success) { |
| showAlert(`Model ${modelName} downloaded successfully!`, 'success', 'download-status'); |
| |
| loadAvailableModels(); |
| } else { |
| showAlert(`Error downloading model: ${data.error}`, 'danger', 'download-status'); |
| } |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| toggleFormElements(downloadModelForm, false); |
| showAlert(`Error downloading model: ${error.message}`, 'danger', 'download-status'); |
| }); |
| } |
| |
| |
| |
| |
| function cloneModel() { |
| const originalModel = document.getElementById('original-model').value; |
| const newModelName = document.getElementById('new-model-name').value; |
| const modificationsText = document.getElementById('modifications')?.value; |
| |
| |
| if (!originalModel || !newModelName) { |
| showAlert('Please select an original model and provide a name for the clone.', 'danger'); |
| return; |
| } |
| |
| |
| let modifications = {}; |
| if (modificationsText) { |
| try { |
| modifications = JSON.parse(modificationsText); |
| } catch (e) { |
| showAlert('Invalid JSON in modifications field.', 'danger'); |
| return; |
| } |
| } |
| |
| |
| toggleFormElements(cloneModelForm, true); |
| |
| |
| showAlert('Cloning model. This may take a while...', 'info', 'clone-status'); |
| |
| |
| fetch('/api/models/clone', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| original_model: originalModel, |
| new_model_name: newModelName, |
| modifications: modifications |
| }), |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| toggleFormElements(cloneModelForm, false); |
| |
| if (data.success) { |
| showAlert(`Model cloned successfully to ${newModelName}!`, 'success', 'clone-status'); |
| |
| loadAvailableModels(); |
| } else { |
| showAlert(`Error cloning model: ${data.error}`, 'danger', 'clone-status'); |
| } |
| }) |
| .catch(error => { |
| console.error('Error:', error); |
| toggleFormElements(cloneModelForm, false); |
| showAlert(`Error cloning model: ${error.message}`, 'danger', 'clone-status'); |
| }); |
| } |
| |
| |
| |
| |
| function loadAvailableModels() { |
| const originalModelSelect = document.getElementById('original-model'); |
| const preferredModelSelect = document.getElementById('preferred-model'); |
| |
| if (!originalModelSelect && !preferredModelSelect) { |
| return; |
| } |
| |
| fetch('/api/models/list') |
| .then(response => response.json()) |
| .then(data => { |
| const models = data.models || []; |
| |
| |
| if (originalModelSelect) { |
| |
| const currentSelection = originalModelSelect.value; |
| |
| |
| originalModelSelect.innerHTML = ''; |
| |
| |
| models.forEach(model => { |
| const option = document.createElement('option'); |
| option.value = model.name; |
| option.textContent = `${model.name} (${model.source})`; |
| originalModelSelect.appendChild(option); |
| }); |
| |
| |
| if (currentSelection && originalModelSelect.querySelector(`option[value="${currentSelection}"]`)) { |
| originalModelSelect.value = currentSelection; |
| } |
| } |
| |
| |
| if (preferredModelSelect) { |
| |
| const currentSelection = preferredModelSelect.value; |
| |
| |
| |
| const existingValues = Array.from(preferredModelSelect.options).map(opt => opt.value); |
| |
| models.forEach(model => { |
| if (!existingValues.includes(model.name)) { |
| const option = document.createElement('option'); |
| option.value = model.name; |
| option.textContent = `${model.name} (${model.source})`; |
| preferredModelSelect.appendChild(option); |
| } |
| }); |
| |
| |
| if (currentSelection) { |
| preferredModelSelect.value = currentSelection; |
| } |
| } |
| }) |
| .catch(error => { |
| console.error('Error loading models:', error); |
| showAlert('Error loading available models', 'danger'); |
| }); |
| } |
| |
| |
| |
| |
| function showAlert(message, type, elementId = null) { |
| if (elementId) { |
| |
| const element = document.getElementById(elementId); |
| if (element) { |
| element.innerHTML = `<div class="alert alert-${type} mt-3">${message}</div>`; |
| } |
| } else { |
| |
| const alertContainer = document.getElementById('alert-container') || document.createElement('div'); |
| alertContainer.id = 'alert-container'; |
| alertContainer.className = 'container mt-3'; |
| |
| const alert = document.createElement('div'); |
| alert.className = `alert alert-${type} alert-dismissible fade show`; |
| alert.role = 'alert'; |
| alert.innerHTML = ` |
| ${message} |
| <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> |
| `; |
| |
| alertContainer.appendChild(alert); |
| |
| |
| if (!document.getElementById('alert-container')) { |
| const contentElement = document.querySelector('main') || document.body; |
| contentElement.insertBefore(alertContainer, contentElement.firstChild); |
| } |
| |
| |
| setTimeout(() => { |
| alert.classList.remove('show'); |
| setTimeout(() => { |
| alert.remove(); |
| if (alertContainer.children.length === 0) { |
| alertContainer.remove(); |
| } |
| }, 150); |
| }, 5000); |
| } |
| } |
| |
| |
| |
| |
| function toggleFormElements(form, disabled) { |
| if (!form) return; |
| |
| const elements = form.querySelectorAll('input, select, textarea, button'); |
| elements.forEach(element => { |
| element.disabled = disabled; |
| }); |
| } |
| }); |
|
|