diff --git a/wwwroot/css/base.css b/wwwroot/css/base.css
index 822f579..833b122 100644
--- a/wwwroot/css/base.css
+++ b/wwwroot/css/base.css
@@ -93,6 +93,19 @@ button.icon-btn:hover {
border-color: transparent;
}
+button.icon-btn[title="Deaktivieren"],
+button.icon-btn[data-tooltip="Deaktivieren"] {
+ border-color: var(--primary);
+ background: var(--primary);
+ color: var(--f1-bg);
+}
+
+.admin-user-row:has(button.icon-btn[title="Deaktivieren"]),
+.admin-user-row:has(button.icon-btn[data-tooltip="Deaktivieren"]) {
+ border-color: var(--primary);
+ filter: brightness(1.1);
+}
+
textarea, code, pre, .tool-input, .tool-diff, .tool-result {
font-family: var(--mono);
font-size: var(--mono-size);
diff --git a/wwwroot/css/form.css b/wwwroot/css/form.css
index d5e3786..b2b7341 100644
--- a/wwwroot/css/form.css
+++ b/wwwroot/css/form.css
@@ -572,6 +572,7 @@ label.skill-item {
.admin-user-list {
display: flex;
flex-direction: column;
+ gap: var(--badge-spacing);
}
.admin-user-row {
@@ -579,6 +580,9 @@ label.skill-item {
align-items: center;
justify-content: space-between;
padding: var(--box-padding);
+ border: 1px solid var(--f1-border);
+ border-radius: var(--border-radius);
+ background: color-mix(in srgb, var(--f1-bg) 25%, transparent);
}
.admin-user-info {
diff --git a/wwwroot/css/placeholder.css b/wwwroot/css/placeholder.css
index 7894262..1b66c91 100644
--- a/wwwroot/css/placeholder.css
+++ b/wwwroot/css/placeholder.css
@@ -25,9 +25,9 @@
justify-content: space-between;
gap: var(--box-spacing);
padding: var(--box-padding);
- background: var(--f1-bg);
- border: var(--border-width) solid var(--f1-border);
+ border: 1px solid var(--f1-border);
border-radius: var(--border-radius);
+ background: color-mix(in srgb, var(--f1-bg) 25%, transparent);
}
.setting-info {
diff --git a/wwwroot/js/pages/api-keys-page.js b/wwwroot/js/pages/api-keys-page.js
index 93bb445..3e2812d 100644
--- a/wwwroot/js/pages/api-keys-page.js
+++ b/wwwroot/js/pages/api-keys-page.js
@@ -98,7 +98,6 @@ registerPage('api-keys', {
var metaSpan = document.createElement('span');
metaSpan.className = 'admin-user-meta';
var parts = [key.provider];
- if (key.isActive) parts.push('✅ Aktiv');
parts.push(formatKeyStatus(key.status));
if (key.plan) parts.push(key.plan);
if (key.checkedAt) parts.push(new Date(key.checkedAt).toLocaleString());
@@ -115,27 +114,50 @@ registerPage('api-keys', {
info.appendChild(urlSpan);
}
info.appendChild(metaSpan);
- var usageBadge = createUsageBadge(key.usage5h, key.usage7d);
- if (usageBadge) info.appendChild(usageBadge);
- var actions = document.createElement('div');
- actions.className = 'admin-user-actions';
+ // Toggle + Usage-Badge nebeneinander
+ var badgeRow = document.createElement('div');
+ badgeRow.style.cssText = 'display:flex;align-items:center;gap:8px;margin-top:2px';
+
+ if (key.isActive) {
+ var deactivateBtn = document.createElement('button');
+ deactivateBtn.className = 'icon-btn';
+ deactivateBtn.title = 'Deaktivieren';
+ deactivateBtn.innerHTML = '';
+ deactivateBtn.addEventListener('click', function() { deactivateKey(key); });
+ badgeRow.appendChild(deactivateBtn);
+ } else {
+ var activateBtn = document.createElement('button');
+ activateBtn.className = 'icon-btn';
+ activateBtn.title = 'Aktivieren';
+ activateBtn.innerHTML = '';
+ activateBtn.addEventListener('click', function() { activateKey(key); });
+ badgeRow.appendChild(activateBtn);
+ }
+
+ var usageBadge = createUsageBadge(key.usage5h, key.usage7d);
+ if (usageBadge) badgeRow.appendChild(usageBadge);
// Status-Zeile (für Check-Ergebnis)
var statusLine = document.createElement('div');
statusLine.className = 'admin-user-meta';
statusLine.style.cssText = 'padding:0 var(--box-padding) .5rem;display:none;font-size:.85em';
- // Check (nur Anthropic)
+ // Check (nur Anthropic) – rechts neben Usage-Badge
if (key.provider === 'anthropic') {
var checkBtn = document.createElement('button');
checkBtn.className = 'icon-btn';
checkBtn.title = 'Key prüfen';
checkBtn.innerHTML = '';
checkBtn.addEventListener('click', function() { checkKey(key, checkBtn, statusLine); });
- actions.appendChild(checkBtn);
+ badgeRow.appendChild(checkBtn);
}
+ info.appendChild(badgeRow);
+
+ var actions = document.createElement('div');
+ actions.className = 'admin-user-actions';
+
// Bearbeiten
var editBtn = document.createElement('button');
editBtn.className = 'icon-btn';
@@ -144,23 +166,6 @@ registerPage('api-keys', {
editBtn.addEventListener('click', function() { startEdit(key); });
actions.appendChild(editBtn);
- // Aktivieren/Deaktivieren
- if (key.isActive) {
- var deactivateBtn = document.createElement('button');
- deactivateBtn.className = 'icon-btn';
- deactivateBtn.title = 'Deaktivieren';
- deactivateBtn.innerHTML = '';
- deactivateBtn.addEventListener('click', function() { deactivateKey(key); });
- actions.appendChild(deactivateBtn);
- } else {
- var activateBtn = document.createElement('button');
- activateBtn.className = 'icon-btn';
- activateBtn.title = 'Aktivieren';
- activateBtn.innerHTML = '';
- activateBtn.addEventListener('click', function() { activateKey(key); });
- actions.appendChild(activateBtn);
- }
-
// Löschen
var deleteBtn = document.createElement('button');
deleteBtn.className = 'icon-btn';
@@ -190,9 +195,8 @@ registerPage('api-keys', {
var origHtml = btn.innerHTML;
btn.innerHTML = '';
btn.disabled = true;
- statusLine.style.display = 'block';
- statusLine.textContent = 'Prüfe…';
- statusLine.style.opacity = '0.5';
+ statusLine.style.display = 'none';
+ statusLine.innerHTML = '';
try {
var result = await apiCheckApiKey(key.keyId);
statusLine.style.opacity = '1';
@@ -322,7 +326,8 @@ registerPage('api-keys', {
function renderScannedKeys() {
scannedList.innerHTML = '';
- if (scannedKeys.length === 0) {
+ var visibleKeys = scannedKeys.filter(function(sk) { return sk.adoptedApiKeyId == null; });
+ if (visibleKeys.length === 0) {
var empty = document.createElement('div');
empty.className = 'admin-user-meta';
empty.style.padding = '1rem 0';
@@ -331,12 +336,10 @@ registerPage('api-keys', {
return;
}
- scannedKeys.forEach(function(sk) {
- var isAdopted = sk.adoptedApiKeyId != null;
+ visibleKeys.forEach(function(sk) {
var row = document.createElement('div');
row.className = 'admin-user-row';
- if (isAdopted) row.style.opacity = '0.5';
var info = document.createElement('div');
info.className = 'admin-user-info';
@@ -354,7 +357,7 @@ registerPage('api-keys', {
var metaSpan = document.createElement('span');
metaSpan.className = 'admin-user-meta';
- var metaParts = isAdopted ? ['📥 Übernommen'] : [];
+ var metaParts = [];
metaParts.push(formatKeyStatus(sk.status));
if (sk.plan && sk.plan !== 'Unknown') metaParts.push(sk.plan);
if (sk.checkedAt) metaParts.push(new Date(sk.checkedAt).toLocaleString());
@@ -367,54 +370,52 @@ registerPage('api-keys', {
var actions = document.createElement('div');
actions.className = 'admin-user-actions';
- if (!isAdopted) {
- // Recheck
- var recheckBtn = document.createElement('button');
- recheckBtn.className = 'icon-btn';
- recheckBtn.title = 'Erneut prüfen';
- recheckBtn.innerHTML = '';
- recheckBtn.addEventListener('click', async function() {
- recheckBtn.innerHTML = '';
- recheckBtn.disabled = true;
- try {
- await apiRecheckScannedKey(sk.scannedKeyId);
- await loadScannedKeys();
- } catch (err) { showToast(err.message, 'error'); }
- finally { recheckBtn.innerHTML = ''; recheckBtn.disabled = false; }
- });
- actions.appendChild(recheckBtn);
+ // Recheck
+ var recheckBtn = document.createElement('button');
+ recheckBtn.className = 'icon-btn';
+ recheckBtn.title = 'Erneut prüfen';
+ recheckBtn.innerHTML = '';
+ recheckBtn.addEventListener('click', async function() {
+ recheckBtn.innerHTML = '';
+ recheckBtn.disabled = true;
+ try {
+ await apiRecheckScannedKey(sk.scannedKeyId);
+ await loadScannedKeys();
+ } catch (err) { showToast(err.message, 'error'); }
+ finally { recheckBtn.innerHTML = ''; recheckBtn.disabled = false; }
+ });
+ actions.appendChild(recheckBtn);
- // Übernehmen (bei valid oder quota_exceeded)
- if (sk.status === 'valid' || sk.status === 'quota_exceeded') {
- var adoptBtn = document.createElement('button');
- adoptBtn.className = 'icon-btn';
- adoptBtn.title = 'Als API-Key übernehmen';
- adoptBtn.innerHTML = '';
- adoptBtn.addEventListener('click', async function() {
- try {
- await apiAdoptScannedKey(sk.scannedKeyId);
- showToast('Key übernommen');
- await loadScannedKeys();
- await loadKeys();
- } catch (err) { showToast(err.message, 'error'); }
- });
- actions.appendChild(adoptBtn);
- }
-
- // Löschen
- var delBtn = document.createElement('button');
- delBtn.className = 'icon-btn';
- delBtn.title = 'Ignorieren';
- delBtn.innerHTML = '';
- delBtn.addEventListener('click', async function() {
+ // Übernehmen (bei valid oder quota_exceeded)
+ if (sk.status === 'valid' || sk.status === 'quota_exceeded') {
+ var adoptBtn = document.createElement('button');
+ adoptBtn.className = 'icon-btn';
+ adoptBtn.title = 'Als API-Key übernehmen';
+ adoptBtn.innerHTML = '';
+ adoptBtn.addEventListener('click', async function() {
try {
- await apiDeleteScannedKey(sk.scannedKeyId);
+ await apiAdoptScannedKey(sk.scannedKeyId);
+ showToast('Key übernommen');
await loadScannedKeys();
+ await loadKeys();
} catch (err) { showToast(err.message, 'error'); }
});
- actions.appendChild(delBtn);
+ actions.appendChild(adoptBtn);
}
+ // Löschen
+ var delBtn = document.createElement('button');
+ delBtn.className = 'icon-btn';
+ delBtn.title = 'Ignorieren';
+ delBtn.innerHTML = '';
+ delBtn.addEventListener('click', async function() {
+ try {
+ await apiDeleteScannedKey(sk.scannedKeyId);
+ await loadScannedKeys();
+ } catch (err) { showToast(err.message, 'error'); }
+ });
+ actions.appendChild(delBtn);
+
row.appendChild(info);
row.appendChild(actions);
scannedList.appendChild(row);