Add OpenAI key save and test controls

This commit is contained in:
rajchales-monito
2026-07-29 21:27:32 +02:00
parent d1cd58c586
commit 9f9f90df2e
4 changed files with 71 additions and 4 deletions
+13
View File
@@ -261,6 +261,19 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
height: 38px;
padding: 0 10px;
}
.ai-actions {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.ai-actions button {
padding: 10px 12px;
}
.ai-actions button:last-child {
background: #edf3ef;
color: var(--ink);
}
.list-tools {
padding: 10px 14px;
border-bottom: 1px solid var(--line);
+4
View File
@@ -192,6 +192,10 @@
<button id="refreshAiModels" type="button">Obnovit</button>
</span>
</label>
<div class="ai-actions">
<button id="saveAiSettings" type="button">Ulozit AI nastaveni</button>
<button id="testOpenAiKey" type="button">Otestovat klic</button>
</div>
</fieldset>
</div>
</section>
+32 -4
View File
@@ -80,11 +80,13 @@ $("#adminSoundRepeat").addEventListener("change", (event) => {
$("#adminSoundTest").addEventListener("click", () => {
playNotifySound({ ignoreMuted: true });
});
$("#translationEnabled").addEventListener("change", saveTranslationSettings);
$("#operatorLanguage").addEventListener("change", saveTranslationSettings);
$("#translationModel").addEventListener("change", saveTranslationSettings);
$("#openaiApiKey").addEventListener("change", saveTranslationSettings);
$("#translationEnabled").addEventListener("change", markAiSettingsDirty);
$("#operatorLanguage").addEventListener("change", markAiSettingsDirty);
$("#translationModel").addEventListener("change", markAiSettingsDirty);
$("#openaiApiKey").addEventListener("input", markAiSettingsDirty);
$("#refreshAiModels").addEventListener("click", loadAiModels);
$("#saveAiSettings").addEventListener("click", saveTranslationSettings);
$("#testOpenAiKey").addEventListener("click", testOpenAiKey);
document.querySelectorAll("[data-settings-tab]").forEach((button) => {
button.addEventListener("click", () => {
const tab = button.dataset.settingsTab;
@@ -403,6 +405,7 @@ function renderSite() {
async function saveTranslationSettings() {
if (!state.site) return;
setOpenAiStatus("Ukladam AI nastaveni...");
const settings = structuredClone(state.site.settings);
settings.translations = {
...(settings.translations || {}),
@@ -414,9 +417,34 @@ async function saveTranslationSettings() {
if (apiKey) settings.translations.openaiApiKey = apiKey;
await saveSite({ settings, isOnline: state.site.isOnline });
$("#openaiApiKey").value = "";
setOpenAiStatus(state.site.settings.translations?.hasOpenaiApiKey
? `Klic ulozeny (${state.site.settings.translations.openaiApiKeyMasked || "sk-..."})`
: "Klic neni ulozeny. Bez nej AI preklady nepobezi.");
await loadAiModels().catch(() => {});
}
function markAiSettingsDirty() {
setOpenAiStatus("AI nastaveni ma neulozene zmeny.");
}
async function testOpenAiKey() {
setOpenAiStatus("Testuji OpenAI klic...");
const result = await api("/api/admin/ai/test", { method: "POST" }).catch((error) => error);
if (result?.ok) {
setOpenAiStatus(`Klic funguje (${result.key || "sk-..."}), dostupnych modelu: ${result.modelCount}.`);
await loadAiModels().catch(() => {});
return;
}
const message = result?.error === "missing_openai_api_key"
? "Klic neni ulozeny. Nejdřív ho vloz a klikni na Ulozit AI nastaveni."
: `Test selhal (${result?.error || "neznamá chyba"}).`;
setOpenAiStatus(message);
}
function setOpenAiStatus(message) {
$("#openaiApiKeyStatus").textContent = message;
}
async function loadAiModels() {
const current = $("#translationModel").value || state.site?.settings?.translations?.model || "gpt-5-mini";
const data = await api("/api/admin/ai/models").catch((error) => error?.models ? error : null);