File size: 6,172 Bytes
f72291c
 
 
 
 
946d512
f72291c
 
 
 
 
 
07b94cd
946d512
 
07b94cd
 
f72291c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946d512
 
 
 
 
 
 
 
f72291c
 
 
946d512
 
 
 
 
 
f72291c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946d512
f72291c
 
 
 
 
 
 
 
 
 
946d512
 
 
 
07b94cd
946d512
 
 
 
07b94cd
946d512
 
 
 
 
 
 
 
 
07b94cd
 
946d512
 
 
07b94cd
 
946d512
07b94cd
946d512
 
07b94cd
946d512
07b94cd
946d512
 
f72291c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dashboard - Ollama</title>
    <link rel="stylesheet" href="/static/style.css">
</head>
<body>
    <div class="container">
        <header>
            <h1>Dashboard</h1>
            <div>
                <span id="ollama-badge" class="status status-pending">Checking...</span>
                <a href="/chat" class="btn btn-primary">Chat</a>
                <button class="btn btn-secondary" onclick="logout()">Logout</button>
            </div>
        </header>

        <div class="dashboard-grid">
            <div class="card">
                <h2>Your Profile</h2>
                <div id="profile"></div>
            </div>

            <div class="card">
                <h2>API Keys</h2>
                <form onsubmit="createApiKey(event)">
                    <input type="text" id="key-name" placeholder="Key name" required>
                    <button type="submit" class="btn btn-primary">Generate</button>
                </form>
                <ul id="api-keys-list" class="key-list"></ul>
            </div>

            <div class="card">
                <h2>Model Status</h2>
                <p><strong>Model:</strong> llama3.1:8b</p>
                <p><strong>Status:</strong> <span id="model-status-text">Checking...</span></p>
                <div id="installed-section">
                    <p><strong>Installed Models:</strong></p>
                    <ul id="installed-models" class="model-list"><li>Loading...</li></ul>
                </div>
                <a href="/chat" class="btn btn-primary" style="width:100%;margin-top:12px;text-align:center">Open Chat</a>
            </div>

            <div class="card full-width">
                <h2>Quick Start</h2>
                <p>Use the chat interface to interact with <strong>llama3.1:8b</strong>.</p>
                <p>Generate API keys above to access the model programmatically via <code>POST /api/chat</code>.</p>
                <p style="margin-top:8px;font-size:0.9rem;color:#666;">
                    Model status: <span id="status-sub">checking...</span>
                </p>
            </div>
        </div>
    </div>

    <script>
        const token = localStorage.getItem('token');
        if (!token) window.location.href = '/login';

        async function api(url, opts = {}) {
            opts.headers = {...opts.headers, 'Authorization': `Bearer ${token}`};
            if (opts.body && typeof opts.body === 'object') {
                opts.headers['Content-Type'] = 'application/json';
                opts.body = JSON.stringify(opts.body);
            }
            const res = await fetch(url, opts);
            if (res.status === 401) { localStorage.removeItem('token'); window.location.href = '/login'; }
            return res;
        }

        function logout() { localStorage.removeItem('token'); window.location.href = '/login'; }

        // Load profile
        api('/api/me').then(r => r.json()).then(data => {
            document.getElementById('profile').innerHTML = `
                <p><strong>Username:</strong> ${data.username}</p>
                <p><strong>Email:</strong> ${data.email}</p>
                <p><strong>Default API Key:</strong> <code>${data.api_key}</code></p>
            `;
        });

        // Check status
        async function loadStatus() {
            const res = await fetch('/api/status', {headers: {'Authorization': `Bearer ${token}`}});
            const data = await res.json();
            const badge = document.getElementById('ollama-badge');
            const statusText = document.getElementById('model-status-text');
            const subText = document.getElementById('status-sub');

            if (data.model) {
                badge.className = 'status status-completed';
                badge.textContent = 'Ready';
                statusText.textContent = 'Ready';
                subText.textContent = 'llama3.1:8b is ready';
            } else if (data.ollama) {
                badge.className = 'status status-downloading';
                badge.textContent = 'Downloading...';
                statusText.textContent = 'Downloading model...';
                subText.textContent = data.message || 'Model is being downloaded';
                setTimeout(loadStatus, 10000);
            } else {
                badge.className = 'status status-error';
                badge.textContent = 'Unavailable';
                statusText.textContent = 'Unavailable';
                subText.textContent = data.message || 'Ollama not reachable';
            }

            // Installed models
            const ul = document.getElementById('installed-models');
            if (data.installed && data.installed.length > 0) {
                ul.innerHTML = data.installed.map(m => `<li>${m}</li>`).join('');
            } else {
                ul.innerHTML = '<li>None yet</li>';
            }
        }
        loadStatus();

        // Load API keys
        async function loadApiKeys() {
            const res = await api('/api/api-keys');
            const data = await res.json();
            const ul = document.getElementById('api-keys-list');
            ul.innerHTML = data.api_keys.map(k => `
                <li>
                    <strong>${k.key_name}</strong>: <code>${k.api_key}</code>
                    <button onclick="revokeKey(${k.id})" class="btn-small btn-danger">Revoke</button>
                </li>
            `).join('');
        }
        loadApiKeys();

        async function createApiKey(e) {
            e.preventDefault();
            const name = document.getElementById('key-name').value;
            await api('/api/api-keys', {method: 'POST', body: {key_name: name}});
            document.getElementById('key-name').value = '';
            loadApiKeys();
        }

        async function revokeKey(id) {
            if (confirm('Revoke this API key?')) {
                await api(`/api/api-keys/${id}`, {method: 'DELETE'});
                loadApiKeys();
            }
        }
    </script>
</body>
</html>