Format: application/javascript
1 document.addEventListener('DOMContentLoaded', function() {
2 const sidebar = document.getElementById('sidebar');
3 const mainContent = document.getElementById('mainContent');
4 document.getElementById('toggleSidebarBtn').addEventListener('click', function() {
5 sidebar.classList.toggle('collapsed');
6 mainContent.classList.toggle('expanded');
7 });
8 document.getElementById('themeToggle').addEventListener('click', function() {
9 document.body.classList.toggle('light-mode');
10 localStorage.setItem('theme', document.body.classList.contains('light-mode') ? 'light' : 'dark');
11 });
12 });
13
14 document.addEventListener('DOMContentLoaded', function() {
15 // Model management
16 fetch('/api/models')
17 .then(res => res.json())
18 .then(data => {
19 $('#model-select').empty()
20 .append(data.models.map(m =>
21 `<option value="${m.name}">${m.name} (${formatBytes(m.size)})</option>`
22 ))
23 })
24 .catch(err => console.error('Error loading models:', err));
25
26 $('#model-form').submit(function(e) {
27 e.preventDefault();
28 const modelName = $('#model-name').val().trim();
29 if (!modelName) return;
30 const modal = bootstrap.Modal.getInstance($('#modelModal')[0]);
31
32 $('#model-status').removeClass('text-danger').text('Pulling model...');
33 fetch('/api/pull-model', {
34 method: 'POST',
35 headers: {'Content-Type': 'application/json'},
36 body: JSON.stringify({model_name: modelName})
37 }).then(() => {
38 modal.hide();
39 location.reload();
40 })
41 .then(res => res.json())
42 .then(data => {
43 if (data.error) throw new Error(data.error);
44 $('#model-status').removeClass('text-danger').text(data.message);
45 $('#model-select').append(
46 `<option value="${model}">${model}</option>`
47 );
48 })
49 .catch(err => {
50 console.error('Model pull error:', err);
51 $('#model-status').addClass('text-danger').html(`
52 <div class="error-alert">
53 <b>Error:</b> ${err.message}<br>
54 <small>Check console for details</small>
55 </div>
56 `);
57 modal.hide();
58 });
59 });
60
61 function formatBytes(bytes) {
62 const units = ['B', 'KB', 'MB', 'GB'];
63 let size = bytes;
64 for (const unit of units) {
65 if (size < 1024) return `${Math.round(size)} ${unit}`;
66 size /= 1024;
67 }
68 return `${Math.round(size)} GB`;
69 }
70
71 const chatForm = document.getElementById('chat-form');
72 const chatInput = document.getElementById('chat-input');
73 const chatBox = document.getElementById('chat-box');
74
75 if (chatForm && chatInput && chatBox) {
76 chatForm.addEventListener('submit', function(e) {
77 e.preventDefault();
78 const userMsg = chatInput.value.trim();
79 if (userMsg) {
80 const msgDiv = document.createElement('div');
81 msgDiv.className = 'user-msg new-message';
82 msgDiv.textContent = userMsg;
83 chatBox.appendChild(msgDiv);
84 chatInput.value = '';
85
86 // Smooth scroll to new message
87 msgDiv.scrollIntoView({
88 behavior: 'smooth',
89 block: 'end'
90 });
91 }
92 });
93 }
94 });