mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 01:35:36 -04:00
Settings: tabbed Add Models card with Local / API tabs
Earlier split into 4 flat cards wasn't what was asked for. Restore to a single 'Add Models' card with two tabs at the top: Local → Add form + Added Local Models list API → Add form + Added API Endpoints list Probe / Clear-offline live on the card header and act on both lists. Active tab is remembered in localStorage so the user lands back where they were. All form/list IDs preserved (adm-epLocalUrl, adm-epList-local, adm-epList-api, etc.) so admin.js continues to work unchanged. Replaces the .adm-section-toggle fold-open JS with a tab-switcher; the fold elements no longer exist so the old handler was already a no-op.
This commit is contained in:
+47
-34
@@ -1998,11 +1998,30 @@
|
||||
|
||||
<!-- ═══ SERVICES TAB ═══ -->
|
||||
<div data-settings-panel="services">
|
||||
<div class="admin-card" id="adm-add-local">
|
||||
<h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg>Add Local Model <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoint)</span></h2>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:10px">Connect a local model server such as Ollama, llama.cpp, or vLLM.</div>
|
||||
<div class="adm-add-section">
|
||||
<div class="admin-model-form">
|
||||
<div class="admin-card" id="adm-models-card">
|
||||
<h2 style="display:flex;align-items:center;gap:8px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><circle cx="6" cy="6" r="1"/><circle cx="6" cy="18" r="1"/></svg>Add Models <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoints)</span>
|
||||
<span style="flex:1"></span>
|
||||
<button class="admin-btn-sm" id="adm-epProbeAllBtn" title="Re-test every endpoint and refresh online status" style="font-size:11px;font-weight:normal;display:inline-flex;align-items:center;gap:4px;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>Probe
|
||||
</button>
|
||||
<button class="admin-btn-sm" id="adm-epClearOfflineBtn" title="Remove all endpoints currently marked offline" style="font-size:11px;font-weight:normal;display:inline-flex;align-items:center;gap:4px;opacity:0.85;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg>Clear offline <span id="adm-epOfflineCount" style="opacity:0.6;margin-left:2px;"></span>
|
||||
</button>
|
||||
</h2>
|
||||
<div class="adm-models-tabs" role="tablist" style="display:flex;gap:4px;border-bottom:1px solid var(--border);margin-bottom:12px;">
|
||||
<button type="button" role="tab" class="adm-models-tab active" data-models-tab="local" aria-selected="true" style="background:transparent;border:0;border-bottom:2px solid var(--accent,var(--red));padding:7px 14px;font-size:12px;font-weight:600;color:var(--fg);cursor:pointer;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg>Local
|
||||
</button>
|
||||
<button type="button" role="tab" class="adm-models-tab" data-models-tab="api" aria-selected="false" style="background:transparent;border:0;border-bottom:2px solid transparent;padding:7px 14px;font-size:12px;font-weight:600;color:var(--fg-muted);cursor:pointer;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>API
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- ── Local tab ─────────────────────────────────────────── -->
|
||||
<div class="adm-models-pane" data-models-pane="local">
|
||||
<div class="admin-toggle-sub" style="margin:0 0 8px 2px;">Add a local model server (Ollama, llama.cpp, vLLM).</div>
|
||||
<div class="adm-add-section">
|
||||
<div class="admin-model-form">
|
||||
<div class="admin-model-form-row">
|
||||
<input id="adm-epLocalUrl" type="text" placeholder="Paste endpoint URL, e.g. http://localhost:11434/v1" style="flex:1">
|
||||
</div>
|
||||
@@ -2039,14 +2058,22 @@
|
||||
</div>
|
||||
<div id="adm-epLocalMsg" class="adm-ep-inline-msg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-card" id="adm-add-api">
|
||||
<h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>Add API <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoint)</span></h2>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:10px">Connect a cloud provider (OpenAI, Anthropic, DeepSeek, OpenRouter, etc.).</div>
|
||||
<div class="adm-add-section">
|
||||
<div class="admin-model-form">
|
||||
<!-- Added Local Models — inline in the Local tab -->
|
||||
<div class="adm-ep-section" style="margin-top:18px;">
|
||||
<div class="adm-ep-section-head" style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;opacity:0.7;margin-bottom:6px;">
|
||||
Added Local Models
|
||||
</div>
|
||||
<div id="adm-epList-local"><div class="admin-empty">Loading...</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── API tab ───────────────────────────────────────────── -->
|
||||
<div class="adm-models-pane hidden" data-models-pane="api">
|
||||
<div class="admin-toggle-sub" style="margin:0 0 8px 2px;">Connect a cloud provider (OpenAI, Anthropic, DeepSeek, OpenRouter, etc.).</div>
|
||||
<div class="adm-add-section">
|
||||
<div class="admin-model-form">
|
||||
<!-- Custom picker (with logos). Hidden native <select> mirrors
|
||||
its value so the existing JS that reads adm-epProvider
|
||||
keeps working unchanged. -->
|
||||
@@ -2109,29 +2136,15 @@
|
||||
<div id="adm-epApiMsg" class="adm-ep-inline-msg"></div>
|
||||
<div id="adm-deviceAuthStatus" class="adm-ep-inline-msg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<h2 style="display:flex;align-items:center;gap:8px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg>Added Local Models <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoints)</span>
|
||||
<span style="flex:1"></span>
|
||||
<button class="admin-btn-sm" id="adm-epProbeAllBtn" title="Re-test every endpoint and refresh online status" style="font-size:11px;font-weight:normal;display:inline-flex;align-items:center;gap:4px;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>Probe
|
||||
</button>
|
||||
<button class="admin-btn-sm" id="adm-epClearOfflineBtn" title="Remove all endpoints currently marked offline" style="font-size:11px;font-weight:normal;display:inline-flex;align-items:center;gap:4px;opacity:0.85;">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg>Clear offline <span id="adm-epOfflineCount" style="opacity:0.6;margin-left:2px;"></span>
|
||||
</button>
|
||||
</h2>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:10px">Manage the local endpoints you've added.</div>
|
||||
<div class="adm-ep-section">
|
||||
<div id="adm-epList-local"><div class="admin-empty">Loading...</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-card">
|
||||
<h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>Added API Endpoints</h2>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:10px">Cloud-provider endpoints (Probe / Clear-offline are shared with Local above).</div>
|
||||
<div class="adm-ep-section">
|
||||
<div id="adm-epList-api"></div>
|
||||
<!-- Added API Endpoints — inline in the API tab -->
|
||||
<div class="adm-ep-section" style="margin-top:18px;">
|
||||
<div class="adm-ep-section-head" style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;opacity:0.7;margin-bottom:6px;">
|
||||
Added API Endpoints
|
||||
</div>
|
||||
<div id="adm-epList-api"><div class="admin-empty">No API endpoints yet.</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+27
-23
@@ -1444,30 +1444,34 @@ function initEndpointForm() {
|
||||
});
|
||||
}
|
||||
|
||||
// Collapsible Add-Models subsections (API / Local). Both start collapsed
|
||||
// so the card is compact; the last-used state is remembered per section
|
||||
// in localStorage so a frequent API-adder doesn't re-expand every time.
|
||||
document.querySelectorAll('#adm-add-api, #adm-add-local').forEach((sec) => {
|
||||
const head = sec.querySelector('.adm-section-toggle');
|
||||
if (!head) return;
|
||||
const key = 'odysseus.addModels.' + sec.id + '.open';
|
||||
let open = false;
|
||||
try { open = localStorage.getItem(key) === '1'; } catch {}
|
||||
const apply = () => {
|
||||
sec.classList.toggle('collapsed', !open);
|
||||
head.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
// Add Models card has Local / API tabs (each tab pairs an Add form
|
||||
// with its corresponding Added list). Remember the active tab in
|
||||
// localStorage so the user lands back where they were.
|
||||
(function wireModelsTabs() {
|
||||
const tabs = document.querySelectorAll('.adm-models-tab');
|
||||
const panes = document.querySelectorAll('.adm-models-pane');
|
||||
if (!tabs.length || !panes.length) return;
|
||||
const KEY = 'odysseus.addModels.activeTab';
|
||||
let active = 'local';
|
||||
try { active = localStorage.getItem(KEY) || 'local'; } catch {}
|
||||
const apply = (name) => {
|
||||
active = name;
|
||||
try { localStorage.setItem(KEY, name); } catch {}
|
||||
tabs.forEach((t) => {
|
||||
const on = t.dataset.modelsTab === name;
|
||||
t.classList.toggle('active', on);
|
||||
t.setAttribute('aria-selected', on ? 'true' : 'false');
|
||||
// Inline style swap so we don't need a CSS rule for active.
|
||||
t.style.borderBottomColor = on ? 'var(--accent, var(--red))' : 'transparent';
|
||||
t.style.color = on ? 'var(--fg)' : 'var(--fg-muted)';
|
||||
});
|
||||
panes.forEach((p) => {
|
||||
p.classList.toggle('hidden', p.dataset.modelsPane !== name);
|
||||
});
|
||||
};
|
||||
apply();
|
||||
const toggle = () => {
|
||||
open = !open;
|
||||
try { localStorage.setItem(key, open ? '1' : '0'); } catch {}
|
||||
apply();
|
||||
};
|
||||
head.addEventListener('click', toggle);
|
||||
head.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); }
|
||||
});
|
||||
});
|
||||
tabs.forEach((t) => t.addEventListener('click', () => apply(t.dataset.modelsTab)));
|
||||
apply(active);
|
||||
})();
|
||||
document.querySelectorAll('.adm-quickstart-section').forEach((sec) => {
|
||||
const head = sec.querySelector('.adm-quickstart-toggle');
|
||||
if (!head) return;
|
||||
|
||||
Reference in New Issue
Block a user