Skip to content

Commit de81b42

Browse files
authored
feat(ui): remove api key handling and small ui adjustments (#4948)
* chore(ui): drop set api key button Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * chore(ui): shore in-progress installs in model view Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(ui): improve text to image view Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
1 parent 06eb7e9 commit de81b42

File tree

9 files changed

+25
-282
lines changed

9 files changed

+25
-282
lines changed

core/http/static/chat.js

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ function toggleLoader(show) {
4242
}
4343
}
4444

45-
function submitKey(event) {
46-
event.preventDefault();
47-
localStorage.setItem("key", document.getElementById("apiKey").value);
48-
document.getElementById("apiKey").blur();
49-
}
50-
5145
function submitSystemPrompt(event) {
5246
event.preventDefault();
5347
localStorage.setItem("system_prompt", document.getElementById("systemPrompt").value);
@@ -62,10 +56,9 @@ function submitPrompt(event) {
6256
const input = document.getElementById("input").value;
6357
Alpine.store("chat").add("user", input, image);
6458
document.getElementById("input").value = "";
65-
const key = localStorage.getItem("key");
6659
const systemPrompt = localStorage.getItem("system_prompt");
6760
Alpine.nextTick(() => { document.getElementById('messages').scrollIntoView(false); });
68-
promptGPT(systemPrompt, key, input);
61+
promptGPT(systemPrompt, input);
6962
}
7063

7164
function readInputImage() {
@@ -82,7 +75,7 @@ function readInputImage() {
8275
}
8376

8477

85-
async function promptGPT(systemPrompt, key, input) {
78+
async function promptGPT(systemPrompt, input) {
8679
const model = document.getElementById("chat-model").value;
8780
// Set class "loader" to the element with "loader" id
8881
//document.getElementById("loader").classList.add("loader");
@@ -160,7 +153,6 @@ function readInputImage() {
160153
const response = await fetch("v1/chat/completions", {
161154
method: "POST",
162155
headers: {
163-
Authorization: `Bearer ${key}`,
164156
"Content-Type": "application/json",
165157
},
166158
body: JSON.stringify({
@@ -266,20 +258,12 @@ function readInputImage() {
266258
document.getElementById("input").focus();
267259
}
268260

269-
document.getElementById("key").addEventListener("submit", submitKey);
270261
document.getElementById("system_prompt").addEventListener("submit", submitSystemPrompt);
271262

272263
document.getElementById("prompt").addEventListener("submit", submitPrompt);
273264
document.getElementById("input").focus();
274265
document.getElementById("input_image").addEventListener("change", readInputImage);
275266

276-
storeKey = localStorage.getItem("key");
277-
if (storeKey) {
278-
document.getElementById("apiKey").value = storeKey;
279-
} else {
280-
document.getElementById("apiKey").value = null;
281-
}
282-
283267
storesystemPrompt = localStorage.getItem("system_prompt");
284268
if (storesystemPrompt) {
285269
document.getElementById("systemPrompt").value = storesystemPrompt;

core/http/static/image.js

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,11 @@
1-
/*
2-
3-
https://github.com/david-haerer/chatapi
4-
5-
MIT License
6-
7-
Copyright (c) 2023 David Härer
8-
Copyright (c) 2024 Ettore Di Giacinto
9-
10-
Permission is hereby granted, free of charge, to any person obtaining a copy
11-
of this software and associated documentation files (the "Software"), to deal
12-
in the Software without restriction, including without limitation the rights
13-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14-
copies of the Software, and to permit persons to whom the Software is
15-
furnished to do so, subject to the following conditions:
16-
17-
The above copyright notice and this permission notice shall be included in all
18-
copies or substantial portions of the Software.
19-
20-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26-
SOFTWARE.
27-
28-
*/
29-
function submitKey(event) {
30-
event.preventDefault();
31-
localStorage.setItem("key", document.getElementById("apiKey").value);
32-
document.getElementById("apiKey").blur();
33-
}
34-
35-
361
function genImage(event) {
372
event.preventDefault();
383
const input = document.getElementById("input").value;
39-
const key = localStorage.getItem("key");
40-
41-
promptDallE(key, input);
424

5+
promptDallE(input);
436
}
447

45-
async function promptDallE(key, input) {
8+
async function promptDallE(input) {
469
document.getElementById("loader").style.display = "block";
4710
document.getElementById("input").value = "";
4811
document.getElementById("input").disabled = true;
@@ -51,7 +14,6 @@ async function promptDallE(key, input) {
5114
const response = await fetch("v1/images/generations", {
5215
method: "POST",
5316
headers: {
54-
Authorization: `Bearer ${key}`,
5517
"Content-Type": "application/json",
5618
},
5719
body: JSON.stringify({
@@ -84,13 +46,6 @@ async function promptDallE(key, input) {
8446
document.getElementById("input").focus();
8547
}
8648

87-
document.getElementById("key").addEventListener("submit", submitKey);
8849
document.getElementById("input").focus();
8950
document.getElementById("genimage").addEventListener("submit", genImage);
9051
document.getElementById("loader").style.display = "none";
91-
92-
const storeKey = localStorage.getItem("key");
93-
if (storeKey) {
94-
document.getElementById("apiKey").value = storeKey;
95-
}
96-

core/http/static/talk.js

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ let isRecording = false;
99
let conversationHistory = [];
1010
let resetTimer;
1111

12-
function getApiKey() {
13-
return document.getElementById('apiKey').value;
14-
}
15-
1612
function getModel() {
1713
return document.getElementById('modelSelect').value;
1814
}
@@ -99,34 +95,13 @@ function stopRecording() {
9995
};
10096
}
10197

102-
function submitKey(event) {
103-
event.preventDefault();
104-
localStorage.setItem("key", document.getElementById("apiKey").value);
105-
document.getElementById("apiKey").blur();
106-
}
107-
108-
document.getElementById("key").addEventListener("submit", submitKey);
109-
110-
111-
storeKey = localStorage.getItem("key");
112-
if (storeKey) {
113-
document.getElementById("apiKey").value = storeKey;
114-
} else {
115-
document.getElementById("apiKey").value = null;
116-
}
117-
118-
11998
async function sendAudioToWhisper(audioBlob) {
12099
const formData = new FormData();
121100
formData.append('file', audioBlob);
122101
formData.append('model', getWhisperModel());
123-
API_KEY = localStorage.getItem("key");
124102

125103
const response = await fetch('v1/audio/transcriptions', {
126104
method: 'POST',
127-
headers: {
128-
'Authorization': `Bearer ${API_KEY}`
129-
},
130105
body: formData
131106
});
132107

@@ -137,14 +112,9 @@ async function sendAudioToWhisper(audioBlob) {
137112

138113
async function sendTextToChatGPT(text) {
139114
conversationHistory.push({ role: "user", content: text });
140-
API_KEY = localStorage.getItem("key");
141115

142116
const response = await fetch('v1/chat/completions', {
143117
method: 'POST',
144-
headers: {
145-
'Authorization': `Bearer ${API_KEY}`,
146-
'Content-Type': 'application/json'
147-
},
148118
body: JSON.stringify({
149119
model: getModel(),
150120
messages: conversationHistory
@@ -161,13 +131,10 @@ async function sendTextToChatGPT(text) {
161131
}
162132

163133
async function getTextToSpeechAudio(text) {
164-
API_KEY = localStorage.getItem("key");
165-
166134
const response = await fetch('v1/audio/speech', {
167135

168136
method: 'POST',
169137
headers: {
170-
'Authorization': `Bearer ${API_KEY}`,
171138
'Content-Type': 'application/json'
172139
},
173140
body: JSON.stringify({

core/http/static/tts.js

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,18 @@
11
// Initialize Alpine store for API key management
22
document.addEventListener('alpine:init', () => {
3-
Alpine.store('chat', {
4-
get key() {
5-
return localStorage.getItem('key') || '';
6-
},
7-
set key(value) {
8-
localStorage.setItem('key', value);
9-
}
10-
});
3+
Alpine.store('chat', { });
114
});
125

13-
function submitKey(event) {
14-
event.preventDefault();
15-
const keyValue = document.getElementById("apiKey").value;
16-
localStorage.setItem("key", keyValue);
17-
18-
// Show brief visual confirmation
19-
const button = event.submitter;
20-
const originalIcon = button.innerHTML;
21-
button.innerHTML = '<i class="fa-solid fa-check text-green-400"></i>';
22-
button.classList.add('bg-green-600');
23-
button.classList.remove('bg-blue-600', 'hover:bg-blue-700');
24-
25-
setTimeout(() => {
26-
button.innerHTML = originalIcon;
27-
button.classList.remove('bg-green-600');
28-
button.classList.add('bg-blue-600', 'hover:bg-blue-700');
29-
}, 1000);
30-
31-
document.getElementById("apiKey").blur();
32-
}
33-
346
function genAudio(event) {
357
event.preventDefault();
368
const input = document.getElementById("input").value;
37-
const key = localStorage.getItem("key");
389

3910
if (!input.trim()) {
4011
showNotification('error', 'Please enter text to convert to speech');
4112
return;
4213
}
4314

44-
if (!key) {
45-
showNotification('warning', 'API key is not set. Please set your API key first.');
46-
return;
47-
}
48-
49-
tts(key, input);
15+
tts(input);
5016
}
5117

5218
function showNotification(type, message) {
@@ -109,7 +75,7 @@ function showNotification(type, message) {
10975
}, 5000);
11076
}
11177

112-
async function tts(key, input) {
78+
async function tts(input) {
11379
// Show loader and prepare UI
11480
const loader = document.getElementById("loader");
11581
const inputField = document.getElementById("input");
@@ -126,7 +92,6 @@ async function tts(key, input) {
12692
const response = await fetch("tts", {
12793
method: "POST",
12894
headers: {
129-
Authorization: `Bearer ${key}`,
13095
"Content-Type": "application/json",
13196
},
13297
body: JSON.stringify({
@@ -224,17 +189,10 @@ async function tts(key, input) {
224189

225190
// Set up event listeners when DOM is loaded
226191
document.addEventListener('DOMContentLoaded', () => {
227-
document.getElementById("key").addEventListener("submit", submitKey);
228192
document.getElementById("input").focus();
229193
document.getElementById("tts").addEventListener("submit", genAudio);
230194
document.getElementById("loader").style.display = "none";
231-
232-
// Initialize stored API key if available
233-
const storeKey = localStorage.getItem("key");
234-
if (storeKey) {
235-
document.getElementById("apiKey").value = storeKey;
236-
}
237-
195+
238196
// Add basic keyboard shortcuts
239197
document.addEventListener('keydown', (e) => {
240198
// Submit on Ctrl+Enter

core/http/views/chat.html

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<script defer src="static/chat.js"></script>
3232
{{ $allGalleryConfigs:=.GalleryConfig }}
3333
{{ $model:=.Model}}
34-
<body class="bg-slate-900 text-gray-100 flex flex-col h-screen" x-data="{ key: $store.chat.key, sidebarOpen: true }">
34+
<body class="bg-slate-900 text-gray-100 flex flex-col h-screen" x-data="{ sidebarOpen: true }">
3535
{{template "views/partials/navbar" .}}
3636

3737
<!-- Main container with sidebar toggle -->
@@ -150,36 +150,9 @@ <h3 class="text-md font-medium">{{ $model }}</h3>
150150
</div>
151151

152152
<!-- Settings tab -->
153-
<div x-show="activeTab === 'settings'" x-data="{ showKeyForm: false, showPromptForm: false }" class="space-y-3">
153+
<div x-show="activeTab === 'settings'" x-data="{ showPromptForm: false }" class="space-y-3">
154154
<button
155-
@click="showKeyForm = !showKeyForm; showPromptForm = false"
156-
class="w-full flex items-center justify-between px-3 py-2 text-sm rounded text-white bg-gray-700 hover:bg-gray-600 transition-colors"
157-
>
158-
<span><i class="fa-solid fa-key mr-2"></i> API Key</span>
159-
<i :class="showKeyForm ? 'fa-chevron-up' : 'fa-chevron-down'" class="fa-solid"></i>
160-
</button>
161-
162-
<div x-show="showKeyForm" class="p-3 bg-gray-700 rounded">
163-
<form id="key" class="flex flex-col space-y-2">
164-
<input
165-
type="password"
166-
id="apiKey"
167-
name="apiKey"
168-
class="bg-gray-800 text-white border border-gray-600 focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 rounded-md shadow-sm p-2 appearance-none"
169-
placeholder="OpenAI API Key"
170-
x-model.lazy="key"
171-
/>
172-
<button
173-
type="submit"
174-
class="px-3 py-2 text-sm rounded text-white bg-blue-600 hover:bg-blue-700 transition-colors"
175-
>
176-
Save API Key
177-
</button>
178-
</form>
179-
</div>
180-
181-
<button
182-
@click="showPromptForm = !showPromptForm; showKeyForm = false"
155+
@click="showPromptForm = !showPromptForm"
183156
class="w-full flex items-center justify-between px-3 py-2 text-sm rounded text-white bg-gray-700 hover:bg-gray-600 transition-colors"
184157
>
185158
<span><i class="fa-solid fa-message mr-2"></i> System Prompt</span>

core/http/views/models.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ <h1 class="text-3xl md:text-4xl font-bold text-white mb-3">
2727
</div>
2828
</div>
2929

30+
{{template "views/partials/inprogress" .}}
31+
3032
<!-- Search and Filter Section -->
3133
<div class="bg-gray-800/70 rounded-xl p-6 mb-8 shadow-lg border border-gray-700/50">
3234
<!-- Search Input -->

0 commit comments

Comments
 (0)