refactor: Inline-Styles durch CSS-Klassen ersetzt
- 40+ Utility-Klassen in form.css (clickable, text-danger, flex-row, loading-state, etc.) - share-menu position/z-index in chat.css statt inline - index.html: 0 Inline-Styles (hidden-Attribut, CSS-Klassen) - 12 JS-Dateien bereinigt: style.cssText/style.* durch classList ersetzt - Bugfix: var(--danger) → var(--dangerous) (nicht existierende Variable) - display:none Toggles → hidden-Attribut wo passend - Hardcoded font-sizes in chat.css → var(--font-size) 15 Dateien, nur Frontend (CSS/JS/HTML), kein Backend
This commit is contained in:
1 parent
e368abced0
commit
ce50633e33
15 files changed
+109
-76
No files matched your search
@@ -241,7 +241,7 @@
|
|||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
color: var(--text) !important;
|
color: var(--text) !important;
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
font-size: 0.85em;
|
font-size: var(--font-size);
|
||||||
transition: background var(--transition-speed), border-color var(--transition-speed);
|
transition: background var(--transition-speed), border-color var(--transition-speed);
|
||||||
max-width: 20em;
|
max-width: 20em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.web-search-source .fa {
|
.web-search-source .fa {
|
||||||
font-size: 0.75em;
|
font-size: var(--font-size);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: .85rem;
|
font-size: var(--font-size);
|
||||||
gap: var(--badge-spacing);
|
gap: var(--badge-spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,6 +979,8 @@
|
|||||||
/* Share Menu */
|
/* Share Menu */
|
||||||
|
|
||||||
.share-menu {
|
.share-menu {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 10000;
|
||||||
background: var(--f2-bg);
|
background: var(--f2-bg);
|
||||||
border: var(--border-width) solid var(--f2-border);
|
border: var(--border-width) solid var(--f2-border);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
|
|||||||
@@ -855,3 +855,42 @@ a.admin-user-meta {
|
|||||||
.db-back-link:hover {
|
.db-back-link:hover {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Utility Classes (Inline-Style Replacements) ── */
|
||||||
|
|
||||||
|
.clickable { cursor: pointer }
|
||||||
|
.semi-dim { opacity: var(--semi-transparent) }
|
||||||
|
.text-danger { color: var(--dangerous) }
|
||||||
|
.text-accent { color: var(--accent) }
|
||||||
|
.text-primary { color: var(--primary) }
|
||||||
|
.text-error { color: var(--color-error) }
|
||||||
|
.text-secondary { color: var(--text-secondary) }
|
||||||
|
.icon-dim { opacity: var(--semi-transparent) }
|
||||||
|
.icon-dim-sm { opacity: var(--semi-transparent); font-size: var(--font-size) }
|
||||||
|
.chevron-separator { opacity: var(--semi-transparent); font-size: var(--font-size); margin: 0 .3em }
|
||||||
|
.pad-v { padding: 1rem 0 }
|
||||||
|
.loading-state { opacity: var(--semi-transparent); pointer-events: none }
|
||||||
|
.flex-row { display: flex; align-items: center; gap: .5rem }
|
||||||
|
.flex-row-tight { display: flex; align-items: center; gap: 8px; margin-top: 2px }
|
||||||
|
.min-w-0 { min-width: 0 }
|
||||||
|
.ml-auto { margin-left: auto }
|
||||||
|
.mr-badge { margin-right: var(--badge-spacing) }
|
||||||
|
.ml-sm { margin-left: 8px }
|
||||||
|
.mt-xs { margin-top: 4px }
|
||||||
|
.font-sm { font-size: var(--font-size) }
|
||||||
|
.semi-transparent { opacity: var(--semi-transparent) }
|
||||||
|
.lh-relaxed { line-height: 1.7 }
|
||||||
|
|
||||||
|
.scan-status { font-size: .85em; color: var(--text-secondary); padding: 0 0 .5rem 0 }
|
||||||
|
.check-status-line { padding: 0 var(--box-padding) .5rem; display: none; font-size: .85em }
|
||||||
|
.empty-hint { padding: 1rem; text-align: center; opacity: .7 }
|
||||||
|
.scanner-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px var(--box-padding); border-bottom: 1px solid var(--border) }
|
||||||
|
|
||||||
|
.event-scanner-status { padding: 1em 2em }
|
||||||
|
.event-scanner-log { white-space: pre-line }
|
||||||
|
|
||||||
|
.remote-hint { font-size: var(--font-size); opacity: var(--semi-transparent); margin-bottom: var(--box-spacing) }
|
||||||
|
.remote-card-content { font-size: var(--font-size); display: flex; align-items: center; gap: var(--box-spacing) }
|
||||||
|
.remote-card-info { flex: 1; opacity: var(--semi-transparent) }
|
||||||
|
.none-card-image { display: flex; align-items: center; justify-content: center }
|
||||||
|
.none-card-icon { font-size: 2em; opacity: var(--semi-transparent) }
|
||||||
+5
-5
@@ -473,7 +473,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="settingsBackupSection" class="settings-section" style="display:none">
|
<section id="settingsBackupSection" class="settings-section" hidden>
|
||||||
<h2>Daten</h2>
|
<h2>Daten</h2>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
@@ -573,7 +573,7 @@
|
|||||||
<div class="form">
|
<div class="form">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>API-Key</h2>
|
<h2>API-Key</h2>
|
||||||
<button id="apiKeysCheckAllBtn" class="section-add-btn" style="margin-right: var(--badge-spacing); margin-left: auto;"><i class="fa fa-refresh"></i> Alle prüfen</button>
|
<button id="apiKeysCheckAllBtn" class="section-add-btn mr-badge ml-auto"><i class="fa fa-refresh"></i> Alle prüfen</button>
|
||||||
<button id="apiKeysNewBtn" class="section-add-btn"><i class="fa fa-plus"></i> Neuer Key</button>
|
<button id="apiKeysNewBtn" class="section-add-btn"><i class="fa fa-plus"></i> Neuer Key</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="apiKeysList" class="admin-user-list"></div>
|
<div id="apiKeysList" class="admin-user-list"></div>
|
||||||
@@ -596,19 +596,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="eventScannerStatus" style="display:none;padding:1em 2em;"></div>
|
<div id="eventScannerStatus" class="event-scanner-status" hidden></div>
|
||||||
|
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>Key Scanner</h2>
|
<h2>Key Scanner</h2>
|
||||||
<div style="display:flex;gap:.5rem;align-items:center">
|
<div class="flex-row">
|
||||||
<button id="recheckAllScannedBtn" class="section-add-btn"><i class="fa fa-refresh"></i> Alle prüfen</button>
|
<button id="recheckAllScannedBtn" class="section-add-btn"><i class="fa fa-refresh"></i> Alle prüfen</button>
|
||||||
<button id="scanQuickBtn" class="section-add-btn"><i class="fa fa-bolt"></i> Quick</button>
|
<button id="scanQuickBtn" class="section-add-btn"><i class="fa fa-bolt"></i> Quick</button>
|
||||||
<button id="scanWebBtn" class="section-add-btn"><i class="fa fa-globe"></i> Web</button>
|
<button id="scanWebBtn" class="section-add-btn"><i class="fa fa-globe"></i> Web</button>
|
||||||
<button id="scanFullBtn" class="section-add-btn"><i class="fa fa-search"></i> Full</button>
|
<button id="scanFullBtn" class="section-add-btn"><i class="fa fa-search"></i> Full</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="scanStatus" style="font-size:.85em;color:var(--text-secondary);padding:0 0 .5rem 0"></div>
|
<div id="scanStatus" class="scan-status"></div>
|
||||||
<div id="scannedKeysList" class="admin-user-list"></div>
|
<div id="scannedKeysList" class="admin-user-list"></div>
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button hidden> </button>
|
<button hidden> </button>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ var AvatarEditor = (function () {
|
|||||||
renderPreview();
|
renderPreview();
|
||||||
|
|
||||||
// Click → Modal öffnen
|
// Click → Modal öffnen
|
||||||
previewEl.style.cursor = 'pointer';
|
previewEl.classList.add('clickable');
|
||||||
previewEl.addEventListener('click', openModal);
|
previewEl.addEventListener('click', openModal);
|
||||||
|
|
||||||
// Paste Handler (global, immer aktiv)
|
// Paste Handler (global, immer aktiv)
|
||||||
@@ -326,7 +326,7 @@ var AvatarEditor = (function () {
|
|||||||
pasteHandler = null;
|
pasteHandler = null;
|
||||||
}
|
}
|
||||||
previewEl.removeEventListener('click', openModal);
|
previewEl.removeEventListener('click', openModal);
|
||||||
previewEl.style.cursor = '';
|
previewEl.classList.remove('clickable');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ function _renderUserTextContent(container, raw, inlineImages) {
|
|||||||
const filePath = ref.replace(/:\d+(-\d+)?$/, '');
|
const filePath = ref.replace(/:\d+(-\d+)?$/, '');
|
||||||
const fileName = filePath.includes('/') ? filePath.substring(filePath.lastIndexOf('/') + 1) : filePath;
|
const fileName = filePath.includes('/') ? filePath.substring(filePath.lastIndexOf('/') + 1) : filePath;
|
||||||
const lineInfo = ref.replace(filePath, '').trim();
|
const lineInfo = ref.replace(filePath, '').trim();
|
||||||
return '<span class="file-ref-chip" data-filepath="' + esc(filePath) + '" title="' + esc(ref) + '" style="cursor:pointer">'
|
return '<span class="file-ref-chip clickable" data-filepath="' + esc(filePath) + '" title="' + esc(ref) + '">'
|
||||||
+ '<i class="fa fa-file-text-o"></i> ' + esc(fileName + lineInfo) + '</span>';
|
+ '<i class="fa fa-file-text-o"></i> ' + esc(fileName + lineInfo) + '</span>';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ function createAttachmentIndicator(messageId, count, namesJson) {
|
|||||||
const ind = document.createElement('div');
|
const ind = document.createElement('div');
|
||||||
ind.className = 'attachment-indicator';
|
ind.className = 'attachment-indicator';
|
||||||
ind.innerHTML = `<i class="fa fa-paperclip"></i> ${count} Datei${count > 1 ? 'en' : ''}` + (nameList ? `: ${esc(nameList)}` : '');
|
ind.innerHTML = `<i class="fa fa-paperclip"></i> ${count} Datei${count > 1 ? 'en' : ''}` + (nameList ? `: ${esc(nameList)}` : '');
|
||||||
ind.style.cursor = 'pointer';
|
ind.classList.add('clickable');
|
||||||
ind.title = 'Klicken zum Anzeigen';
|
ind.title = 'Klicken zum Anzeigen';
|
||||||
ind.addEventListener('click', () => loadAndShowAttachments(messageId, ind));
|
ind.addEventListener('click', () => loadAndShowAttachments(messageId, ind));
|
||||||
return ind;
|
return ind;
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ function _renderMessagesIntoFragment(fragment, msgs, imageMessageIds, opts) {
|
|||||||
case 'error': {
|
case 'error': {
|
||||||
var errDiv = document.createElement('div');
|
var errDiv = document.createElement('div');
|
||||||
errDiv.className = 'msg system-info' + (archived ? ' archived' : '');
|
errDiv.className = 'msg system-info' + (archived ? ' archived' : '');
|
||||||
errDiv.style.color = 'var(--dangerous)';
|
errDiv.classList.add('text-danger');
|
||||||
errDiv.textContent = (msg.content || '').trim();
|
errDiv.textContent = (msg.content || '').trim();
|
||||||
fragment.appendChild(errDiv);
|
fragment.appendChild(errDiv);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+17
-19
@@ -72,7 +72,7 @@ async function showSystemPromptModal(sessionId) {
|
|||||||
body.innerHTML = '';
|
body.innerHTML = '';
|
||||||
_renderSystemPromptBlocks(body, blocks);
|
_renderSystemPromptBlocks(body, blocks);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
body.innerHTML = '<div class="sp-loading" style="color:var(--dangerous)">Fehler beim Laden des System-Prompts</div>';
|
body.innerHTML = '<div class="sp-loading text-danger">Fehler beim Laden des System-Prompts</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ function showKreaImageModal(titleText, fullUrl) {
|
|||||||
img.className = 'krea-modal-image';
|
img.className = 'krea-modal-image';
|
||||||
img.alt = titleText;
|
img.alt = titleText;
|
||||||
img.addEventListener('error', function() {
|
img.addEventListener('error', function() {
|
||||||
body.innerHTML = '<div class="sp-loading" style="color:var(--dangerous)">Bild konnte nicht geladen werden</div>';
|
body.innerHTML = '<div class="sp-loading text-danger">Bild konnte nicht geladen werden</div>';
|
||||||
});
|
});
|
||||||
|
|
||||||
body.appendChild(img);
|
body.appendChild(img);
|
||||||
@@ -137,7 +137,7 @@ function _openPickerModal(title, items, currentId, onSelect, options) {
|
|||||||
const noneCard = document.createElement('div');
|
const noneCard = document.createElement('div');
|
||||||
noneCard.className = 'card agent-picker-item' + (!currentId ? ' selected' : '');
|
noneCard.className = 'card agent-picker-item' + (!currentId ? ' selected' : '');
|
||||||
noneCard.innerHTML = `
|
noneCard.innerHTML = `
|
||||||
<div class="card-image" style="display:flex;align-items:center;justify-content:center"><i class="fa ${esc(noneIcon)}" style="font-size:2em;opacity:var(--semi-transparent)"></i></div>
|
<div class="card-image none-card-image"><i class="fa ${esc(noneIcon)} none-card-icon"></i></div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="card-title-row">
|
<div class="card-title-row">
|
||||||
<span class="card-title">${esc(noneLabel)}</span>
|
<span class="card-title">${esc(noneLabel)}</span>
|
||||||
@@ -268,16 +268,14 @@ async function showOpenClawImportModal(sessionId) {
|
|||||||
var confirmed = confirm('OpenClaw-Session importieren?\n\nSession: ' + openclawSession.sessionId.substring(0, 8) + '…\n' + openclawSession.totalMessages + ' Nachrichten\n\nVorhandene Imports werden ersetzt.');
|
var confirmed = confirm('OpenClaw-Session importieren?\n\nSession: ' + openclawSession.sessionId.substring(0, 8) + '…\n' + openclawSession.totalMessages + ' Nachrichten\n\nVorhandene Imports werden ersetzt.');
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
|
|
||||||
card.style.opacity = '0.5';
|
card.classList.add('loading-state');
|
||||||
card.style.pointerEvents = 'none';
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var result = await apiImportOpenclawSession(openclawSession.sessionId, sessionId);
|
var result = await apiImportOpenclawSession(openclawSession.sessionId, sessionId);
|
||||||
close();
|
close();
|
||||||
showToast(result.messageCount + ' Nachrichten in ' + result.chainCount + ' Chains importiert', 'success');
|
showToast(result.messageCount + ' Nachrichten in ' + result.chainCount + ' Chains importiert', 'success');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
card.style.opacity = '1';
|
card.classList.remove('loading-state');
|
||||||
card.style.pointerEvents = '';
|
|
||||||
showToast('Import fehlgeschlagen: ' + e.message, 'error');
|
showToast('Import fehlgeschlagen: ' + e.message, 'error');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -288,7 +286,7 @@ async function showOpenClawImportModal(sessionId) {
|
|||||||
|
|
||||||
body.appendChild(list);
|
body.appendChild(list);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
body.innerHTML = '<div class="sp-loading" style="color:var(--dangerous)">Fehler: ' + esc(e.message) + '</div>';
|
body.innerHTML = '<div class="sp-loading text-danger">Fehler: ' + esc(e.message) + '</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,14 +306,14 @@ async function showRemoteModal(sessionId) {
|
|||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.className = 'sp-loading';
|
empty.className = 'sp-loading';
|
||||||
empty.innerHTML = 'Keine Remote-Verbindungen aktiv.<br><br>' +
|
empty.innerHTML = 'Keine Remote-Verbindungen aktiv.<br><br>' +
|
||||||
'<span style="font-size:var(--font-size);opacity:var(--semi-transparent)">Auf dem Windows-PC ausführen:<br>' +
|
'<span class="font-sm semi-transparent">Auf dem Windows-PC ausführen:<br>' +
|
||||||
'<code>irm ' + esc(location.origin) + '/remote | iex</code></span>';
|
'<code>irm ' + esc(location.origin) + '/remote | iex</code></span>';
|
||||||
body.appendChild(empty);
|
body.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hint = document.createElement('div');
|
var hint = document.createElement('div');
|
||||||
hint.style.cssText = 'font-size:var(--font-size);opacity:var(--semi-transparent);margin-bottom:var(--box-spacing)';
|
hint.className = 'remote-hint';
|
||||||
hint.textContent = 'Verbindung auswählen um Remote-Befehle in dieser Session zu ermöglichen:';
|
hint.textContent = 'Verbindung auswählen um Remote-Befehle in dieser Session zu ermöglichen:';
|
||||||
body.appendChild(hint);
|
body.appendChild(hint);
|
||||||
|
|
||||||
@@ -323,7 +321,7 @@ async function showRemoteModal(sessionId) {
|
|||||||
var conn = connections[i];
|
var conn = connections[i];
|
||||||
var card = document.createElement('div');
|
var card = document.createElement('div');
|
||||||
card.className = 'sp-block';
|
card.className = 'sp-block';
|
||||||
card.style.cursor = 'pointer';
|
card.classList.add('clickable');
|
||||||
|
|
||||||
var isAssigned = conn.assignedSessionId === sessionId;
|
var isAssigned = conn.assignedSessionId === sessionId;
|
||||||
var isAssignedOther = conn.assignedSessionId && conn.assignedSessionId !== sessionId;
|
var isAssignedOther = conn.assignedSessionId && conn.assignedSessionId !== sessionId;
|
||||||
@@ -331,17 +329,17 @@ async function showRemoteModal(sessionId) {
|
|||||||
var label = document.createElement('div');
|
var label = document.createElement('div');
|
||||||
label.className = 'sp-block-label';
|
label.className = 'sp-block-label';
|
||||||
var statusIcon = isAssigned ? 'fa-check-circle' : (isAssignedOther ? 'fa-link' : 'fa-desktop');
|
var statusIcon = isAssigned ? 'fa-check-circle' : (isAssignedOther ? 'fa-link' : 'fa-desktop');
|
||||||
var statusColor = isAssigned ? 'color:var(--primary)' : '';
|
var statusClass = isAssigned ? ' text-primary' : '';
|
||||||
label.innerHTML = '<i class="fa ' + statusIcon + '" style="' + statusColor + '"></i> ' +
|
label.innerHTML = '<i class="fa ' + statusIcon + statusClass + '"></i> ' +
|
||||||
esc(conn.username || '?') + '@' + esc(conn.hostname || '?');
|
esc(conn.username || '?') + '@' + esc(conn.hostname || '?');
|
||||||
card.appendChild(label);
|
card.appendChild(label);
|
||||||
|
|
||||||
var content = document.createElement('div');
|
var content = document.createElement('div');
|
||||||
content.className = 'sp-block-content';
|
content.className = 'sp-block-content';
|
||||||
content.style.cssText = 'font-size:var(--font-size);display:flex;align-items:center;gap:var(--box-spacing)';
|
content.className = 'remote-card-content';
|
||||||
|
|
||||||
var info = document.createElement('span');
|
var info = document.createElement('span');
|
||||||
info.style.cssText = 'flex:1;opacity:var(--semi-transparent)';
|
info.className = 'remote-card-info';
|
||||||
var connDate = new Date(conn.connectedAt);
|
var connDate = new Date(conn.connectedAt);
|
||||||
info.textContent = conn.os + ' • Verbunden seit ' + connDate.toLocaleTimeString('de');
|
info.textContent = conn.os + ' • Verbunden seit ' + connDate.toLocaleTimeString('de');
|
||||||
content.appendChild(info);
|
content.appendChild(info);
|
||||||
@@ -349,14 +347,14 @@ async function showRemoteModal(sessionId) {
|
|||||||
var btn = document.createElement('button');
|
var btn = document.createElement('button');
|
||||||
if (isAssigned) {
|
if (isAssigned) {
|
||||||
btn.textContent = 'Trennen';
|
btn.textContent = 'Trennen';
|
||||||
btn.style.cssText = 'color:var(--dangerous)';
|
btn.classList.add('text-danger');
|
||||||
} else if (isAssignedOther) {
|
} else if (isAssignedOther) {
|
||||||
btn.textContent = 'Andere Session';
|
btn.textContent = 'Andere Session';
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.style.cssText = 'opacity:var(--semi-transparent)';
|
btn.classList.add('semi-transparent');
|
||||||
} else {
|
} else {
|
||||||
btn.textContent = 'Verbinden';
|
btn.textContent = 'Verbinden';
|
||||||
btn.style.cssText = 'color:var(--primary)';
|
btn.classList.add('text-primary');
|
||||||
}
|
}
|
||||||
content.appendChild(btn);
|
content.appendChild(btn);
|
||||||
|
|
||||||
@@ -383,7 +381,7 @@ async function showRemoteModal(sessionId) {
|
|||||||
})(conn, isAssigned);
|
})(conn, isAssigned);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
body.innerHTML = '<div class="sp-loading" style="color:var(--dangerous)">Fehler beim Laden: ' + esc(e.message) + '</div>';
|
body.innerHTML = '<div class="sp-loading text-danger">Fehler beim Laden: ' + esc(e.message) + '</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,10 +140,8 @@ function _showShareMenu(anchorBtn) {
|
|||||||
|
|
||||||
// Positionierung
|
// Positionierung
|
||||||
const rect = anchorBtn.getBoundingClientRect();
|
const rect = anchorBtn.getBoundingClientRect();
|
||||||
menu.style.position = 'fixed';
|
|
||||||
menu.style.top = (rect.bottom + 4) + 'px';
|
menu.style.top = (rect.bottom + 4) + 'px';
|
||||||
menu.style.left = rect.left + 'px';
|
menu.style.left = rect.left + 'px';
|
||||||
menu.style.zIndex = '10000';
|
|
||||||
|
|
||||||
document.body.appendChild(menu);
|
document.body.appendChild(menu);
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
if (keys.length === 0) {
|
if (keys.length === 0) {
|
||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.className = 'admin-user-meta';
|
empty.className = 'admin-user-meta pad-v';
|
||||||
empty.style.padding = '1rem 0';
|
|
||||||
empty.textContent = 'Keine API-Keys konfiguriert.';
|
empty.textContent = 'Keine API-Keys konfiguriert.';
|
||||||
list.appendChild(empty);
|
list.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
@@ -118,13 +117,13 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
// Toggle + Usage-Badge nebeneinander
|
// Toggle + Usage-Badge nebeneinander
|
||||||
var badgeRow = document.createElement('div');
|
var badgeRow = document.createElement('div');
|
||||||
badgeRow.style.cssText = 'display:flex;align-items:center;gap:8px;margin-top:2px';
|
badgeRow.className = 'flex-row-tight';
|
||||||
|
|
||||||
var publicBtn = document.createElement('button');
|
var publicBtn = document.createElement('button');
|
||||||
publicBtn.className = 'icon-btn';
|
publicBtn.className = 'icon-btn';
|
||||||
publicBtn.title = key.isPublic ? 'Öffentlich (klicken zum Privatschalten)' : 'Privat (klicken zum Veröffentlichen)';
|
publicBtn.title = key.isPublic ? 'Öffentlich (klicken zum Privatschalten)' : 'Privat (klicken zum Veröffentlichen)';
|
||||||
publicBtn.innerHTML = key.isPublic
|
publicBtn.innerHTML = key.isPublic
|
||||||
? '<i class="fa fa-globe" style="color:var(--accent)"></i>'
|
? '<i class="fa fa-globe text-accent"></i>'
|
||||||
: '<i class="fa fa-lock"></i>';
|
: '<i class="fa fa-lock"></i>';
|
||||||
publicBtn.addEventListener('click', function() { togglePublic(key); });
|
publicBtn.addEventListener('click', function() { togglePublic(key); });
|
||||||
badgeRow.appendChild(publicBtn);
|
badgeRow.appendChild(publicBtn);
|
||||||
@@ -135,7 +134,7 @@ registerPage('api-keys', {
|
|||||||
// Status-Zeile (für Check-Ergebnis)
|
// Status-Zeile (für Check-Ergebnis)
|
||||||
var statusLine = document.createElement('div');
|
var statusLine = document.createElement('div');
|
||||||
statusLine.className = 'admin-user-meta';
|
statusLine.className = 'admin-user-meta';
|
||||||
statusLine.style.cssText = 'padding:0 var(--box-padding) .5rem;display:none;font-size:.85em';
|
statusLine.className = 'admin-user-meta check-status-line';
|
||||||
|
|
||||||
// Check – rechts neben Usage-Badge
|
// Check – rechts neben Usage-Badge
|
||||||
if (key.provider === 'anthropic' || key.provider === 'openai' || key.provider === 'google') {
|
if (key.provider === 'anthropic' || key.provider === 'openai' || key.provider === 'google') {
|
||||||
@@ -202,7 +201,7 @@ registerPage('api-keys', {
|
|||||||
text.textContent = parts.join(' · ');
|
text.textContent = parts.join(' · ');
|
||||||
statusLine.appendChild(text);
|
statusLine.appendChild(text);
|
||||||
var badge = createUsageBadge(result.usage5h, result.usage7d);
|
var badge = createUsageBadge(result.usage5h, result.usage7d);
|
||||||
if (badge) { badge.style.marginTop = '4px'; statusLine.appendChild(badge); }
|
if (badge) { badge.classList.add('mt-xs'); statusLine.appendChild(badge); }
|
||||||
} else {
|
} else {
|
||||||
statusLine.textContent = '❌ ' + (result.message || 'Unbekannter Fehler');
|
statusLine.textContent = '❌ ' + (result.message || 'Unbekannter Fehler');
|
||||||
}
|
}
|
||||||
@@ -350,7 +349,7 @@ registerPage('api-keys', {
|
|||||||
if (!summary || summary.length === 0) {
|
if (!summary || summary.length === 0) {
|
||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.className = 'admin-user-meta';
|
empty.className = 'admin-user-meta';
|
||||||
empty.style.padding = '1rem 0';
|
empty.className = 'admin-user-meta pad-v';
|
||||||
empty.textContent = 'Keine gescannten Keys vorhanden.';
|
empty.textContent = 'Keine gescannten Keys vorhanden.';
|
||||||
scannedList.appendChild(empty);
|
scannedList.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
@@ -358,8 +357,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
summary.forEach(function(s) {
|
summary.forEach(function(s) {
|
||||||
var row = document.createElement('div');
|
var row = document.createElement('div');
|
||||||
row.className = 'admin-user-row';
|
row.className = 'admin-user-row clickable';
|
||||||
row.style.cursor = 'pointer';
|
|
||||||
|
|
||||||
var info = document.createElement('div');
|
var info = document.createElement('div');
|
||||||
info.className = 'admin-user-info';
|
info.className = 'admin-user-info';
|
||||||
@@ -382,7 +380,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
var badge = document.createElement('div');
|
var badge = document.createElement('div');
|
||||||
badge.className = 'admin-user-actions';
|
badge.className = 'admin-user-actions';
|
||||||
badge.innerHTML = '<i class="fa fa-chevron-right" style="opacity:.5"></i>';
|
badge.innerHTML = '<i class="fa fa-chevron-right icon-dim"></i>';
|
||||||
|
|
||||||
row.appendChild(info);
|
row.appendChild(info);
|
||||||
row.appendChild(badge);
|
row.appendChild(badge);
|
||||||
@@ -397,8 +395,7 @@ registerPage('api-keys', {
|
|||||||
// Zurück-Button
|
// Zurück-Button
|
||||||
var backRow = document.createElement('div');
|
var backRow = document.createElement('div');
|
||||||
backRow.className = 'admin-user-row';
|
backRow.className = 'admin-user-row';
|
||||||
backRow.style.cursor = 'pointer';
|
backRow.classList.add('clickable', 'semi-dim');
|
||||||
backRow.style.opacity = '.7';
|
|
||||||
var backInfo = document.createElement('div');
|
var backInfo = document.createElement('div');
|
||||||
backInfo.className = 'admin-user-info';
|
backInfo.className = 'admin-user-info';
|
||||||
var backName = document.createElement('span');
|
var backName = document.createElement('span');
|
||||||
@@ -414,7 +411,7 @@ registerPage('api-keys', {
|
|||||||
var uncheckedKeys = visibleKeys.filter(function(sk) { return sk.status === 'unchecked'; });
|
var uncheckedKeys = visibleKeys.filter(function(sk) { return sk.status === 'unchecked'; });
|
||||||
if (uncheckedKeys.length > 0) {
|
if (uncheckedKeys.length > 0) {
|
||||||
var toolbar = document.createElement('div');
|
var toolbar = document.createElement('div');
|
||||||
toolbar.style.cssText = 'display:flex;align-items:center;gap:8px;padding:8px var(--box-padding);border-bottom:1px solid var(--border)';
|
toolbar.className = 'scanner-toolbar';
|
||||||
|
|
||||||
var checkUncheckedBtn = document.createElement('button');
|
var checkUncheckedBtn = document.createElement('button');
|
||||||
checkUncheckedBtn.className = 'section-add-btn';
|
checkUncheckedBtn.className = 'section-add-btn';
|
||||||
@@ -422,7 +419,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
var progressSpan = document.createElement('span');
|
var progressSpan = document.createElement('span');
|
||||||
progressSpan.className = 'admin-user-meta';
|
progressSpan.className = 'admin-user-meta';
|
||||||
progressSpan.style.marginLeft = '8px';
|
progressSpan.classList.add('ml-sm');
|
||||||
|
|
||||||
toolbar.appendChild(checkUncheckedBtn);
|
toolbar.appendChild(checkUncheckedBtn);
|
||||||
toolbar.appendChild(progressSpan);
|
toolbar.appendChild(progressSpan);
|
||||||
@@ -435,7 +432,7 @@ registerPage('api-keys', {
|
|||||||
var stopBtn = document.createElement('button');
|
var stopBtn = document.createElement('button');
|
||||||
stopBtn.className = 'icon-btn';
|
stopBtn.className = 'icon-btn';
|
||||||
stopBtn.title = 'Abbrechen';
|
stopBtn.title = 'Abbrechen';
|
||||||
stopBtn.innerHTML = '<i class="fa fa-stop" style="color:var(--danger)"></i>';
|
stopBtn.innerHTML = '<i class="fa fa-stop text-danger"></i>';
|
||||||
stopBtn.addEventListener('click', function() { checkUncheckedAbort = true; });
|
stopBtn.addEventListener('click', function() { checkUncheckedAbort = true; });
|
||||||
toolbar.appendChild(stopBtn);
|
toolbar.appendChild(stopBtn);
|
||||||
|
|
||||||
@@ -474,7 +471,7 @@ registerPage('api-keys', {
|
|||||||
if (visibleKeys.length === 0) {
|
if (visibleKeys.length === 0) {
|
||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.className = 'admin-user-meta';
|
empty.className = 'admin-user-meta';
|
||||||
empty.style.padding = '1rem 0';
|
empty.className = 'admin-user-meta pad-v';
|
||||||
empty.textContent = 'Keine nicht-übernommenen Keys in dieser Kategorie.';
|
empty.textContent = 'Keine nicht-übernommenen Keys in dieser Kategorie.';
|
||||||
scannedList.appendChild(empty);
|
scannedList.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
@@ -487,7 +484,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
var info = document.createElement('div');
|
var info = document.createElement('div');
|
||||||
info.className = 'admin-user-info';
|
info.className = 'admin-user-info';
|
||||||
info.style.minWidth = '0';
|
info.classList.add('min-w-0');
|
||||||
|
|
||||||
if (sk.sourceUrl) {
|
if (sk.sourceUrl) {
|
||||||
var nameSpan = document.createElement('a');
|
var nameSpan = document.createElement('a');
|
||||||
@@ -540,7 +537,7 @@ registerPage('api-keys', {
|
|||||||
var adoptBtn = document.createElement('button');
|
var adoptBtn = document.createElement('button');
|
||||||
adoptBtn.className = 'icon-btn';
|
adoptBtn.className = 'icon-btn';
|
||||||
adoptBtn.title = 'Als API-Key übernehmen';
|
adoptBtn.title = 'Als API-Key übernehmen';
|
||||||
adoptBtn.innerHTML = '<i class="fa fa-plus-circle" style="color:var(--accent)"></i>';
|
adoptBtn.innerHTML = '<i class="fa fa-plus-circle text-accent"></i>';
|
||||||
adoptBtn.addEventListener('click', async function(e) {
|
adoptBtn.addEventListener('click', async function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
try {
|
try {
|
||||||
@@ -582,7 +579,7 @@ registerPage('api-keys', {
|
|||||||
|
|
||||||
async function loadScannedKeysByType(type) {
|
async function loadScannedKeysByType(type) {
|
||||||
selectedType = type;
|
selectedType = type;
|
||||||
scannedList.innerHTML = '<div class="admin-user-meta" style="padding:1rem 0"><i class="fa fa-spinner fa-spin"></i> Lade Keys…</div>';
|
scannedList.innerHTML = '<div class="admin-user-meta pad-v"><i class="fa fa-spinner fa-spin"></i> Lade Keys…</div>';
|
||||||
try {
|
try {
|
||||||
scannedKeys = await apiGetScannedKeys(type);
|
scannedKeys = await apiGetScannedKeys(type);
|
||||||
renderScannedKeys();
|
renderScannedKeys();
|
||||||
@@ -619,8 +616,8 @@ registerPage('api-keys', {
|
|||||||
if (!el) return;
|
if (!el) return;
|
||||||
try {
|
try {
|
||||||
var s = await apiEventScannerStatus();
|
var s = await apiEventScannerStatus();
|
||||||
if (!s.enabled) { el.style.display = 'none'; return; }
|
if (!s.enabled) { el.hidden = true; return; }
|
||||||
el.style.display = 'block';
|
el.hidden = false;
|
||||||
|
|
||||||
// Status-Zeile
|
// Status-Zeile
|
||||||
var parts = ['🔴 Event Scanner'];
|
var parts = ['🔴 Event Scanner'];
|
||||||
@@ -651,26 +648,27 @@ registerPage('api-keys', {
|
|||||||
// Immer klickbare Status-Zeile rendern
|
// Immer klickbare Status-Zeile rendern
|
||||||
var wasOpen = false;
|
var wasOpen = false;
|
||||||
var oldLog = document.getElementById('eventScannerLog');
|
var oldLog = document.getElementById('eventScannerLog');
|
||||||
if (oldLog) wasOpen = oldLog.style.display !== 'none';
|
if (oldLog) wasOpen = !oldLog.hidden;
|
||||||
|
|
||||||
el.innerHTML = '';
|
el.innerHTML = '';
|
||||||
var statusEl = document.createElement('div');
|
var statusEl = document.createElement('div');
|
||||||
statusEl.style.cssText = 'cursor:pointer';
|
statusEl.className = 'clickable';
|
||||||
statusEl.title = logLines.length > 0 ? 'Klicken für Log' : '';
|
statusEl.title = logLines.length > 0 ? 'Klicken für Log' : '';
|
||||||
statusEl.textContent = statusLine;
|
statusEl.textContent = statusLine;
|
||||||
el.appendChild(statusEl);
|
el.appendChild(statusEl);
|
||||||
|
|
||||||
var logEl = document.createElement('div');
|
var logEl = document.createElement('div');
|
||||||
logEl.id = 'eventScannerLog';
|
logEl.id = 'eventScannerLog';
|
||||||
logEl.style.cssText = 'white-space:pre-line;display:none';
|
logEl.className = 'event-scanner-log';
|
||||||
|
logEl.hidden = true;
|
||||||
logEl.textContent = logLines.length > 0 ? logLines.join('\n') : 'Noch keine Log-Einträge…';
|
logEl.textContent = logLines.length > 0 ? logLines.join('\n') : 'Noch keine Log-Einträge…';
|
||||||
if (wasOpen) logEl.style.display = 'block';
|
if (wasOpen) logEl.hidden = false;
|
||||||
el.appendChild(logEl);
|
el.appendChild(logEl);
|
||||||
|
|
||||||
statusEl.addEventListener('click', function() {
|
statusEl.addEventListener('click', function() {
|
||||||
logEl.style.display = logEl.style.display === 'none' ? 'block' : 'none';
|
logEl.hidden = !logEl.hidden;
|
||||||
});
|
});
|
||||||
} catch(e) { el.style.display = 'none'; }
|
} catch(e) { el.hidden = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatScanProgress(s) {
|
function formatScanProgress(s) {
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ function _renderChatUsageBadge(container, key) {
|
|||||||
_showKeySwitchModal();
|
_showKeySwitchModal();
|
||||||
});
|
});
|
||||||
badge.title = (key.name || 'API Key') + ' · ' + (key.plan || '?');
|
badge.title = (key.name || 'API Key') + ' · ' + (key.plan || '?');
|
||||||
badge.style.cursor = 'pointer';
|
badge.classList.add('clickable');
|
||||||
container.appendChild(badge);
|
container.appendChild(badge);
|
||||||
|
|
||||||
// Check-Button nur für Admins
|
// Check-Button nur für Admins
|
||||||
@@ -143,7 +143,7 @@ async function _showKeySwitchModal() {
|
|||||||
|
|
||||||
if (keys.length === 0) {
|
if (keys.length === 0) {
|
||||||
var empty = document.createElement('div');
|
var empty = document.createElement('div');
|
||||||
empty.style.cssText = 'padding:1rem;text-align:center;opacity:0.7';
|
empty.className = 'empty-hint';
|
||||||
empty.textContent = 'Keine Keys verfügbar. Ein Admin muss Keys als öffentlich markieren.';
|
empty.textContent = 'Keine Keys verfügbar. Ein Admin muss Keys als öffentlich markieren.';
|
||||||
body.appendChild(empty);
|
body.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
@@ -183,18 +183,16 @@ async function _showKeySwitchModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key.keyId !== selectedKeyId) {
|
if (key.keyId !== selectedKeyId) {
|
||||||
row.style.cursor = 'pointer';
|
row.classList.add('clickable');
|
||||||
row.addEventListener('click', async function() {
|
row.addEventListener('click', async function() {
|
||||||
row.style.opacity = '0.5';
|
row.classList.add('loading-state');
|
||||||
row.style.pointerEvents = 'none';
|
|
||||||
try {
|
try {
|
||||||
await apiSelectApiKey(key.keyId);
|
await apiSelectApiKey(key.keyId);
|
||||||
close();
|
close();
|
||||||
await _initChatUsageBadge();
|
await _initChatUsageBadge();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error('Key switch failed:', e);
|
console.error('Key switch failed:', e);
|
||||||
row.style.opacity = '';
|
row.classList.remove('loading-state');
|
||||||
row.style.pointerEvents = '';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,10 +160,10 @@ function updateCronPreview(input, preview) {
|
|||||||
const desc = describeCron(expr);
|
const desc = describeCron(expr);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
preview.textContent = desc;
|
preview.textContent = desc;
|
||||||
preview.style.color = '';
|
preview.classList.remove('text-error');
|
||||||
} else {
|
} else {
|
||||||
preview.textContent = 'Ungültige Cron-Expression';
|
preview.textContent = 'Ungültige Cron-Expression';
|
||||||
preview.style.color = 'var(--color-error)';
|
preview.classList.add('text-error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ registerPage('db-explorer', {
|
|||||||
|
|
||||||
async function loadTableData(name, page) {
|
async function loadTableData(name, page) {
|
||||||
currentTable = name;
|
currentTable = name;
|
||||||
titleEl.innerHTML = '<span class="db-back-link">Datenbank-Explorer</span> <i class="fa fa-chevron-right" style="opacity:.4;font-size:.7em;margin:0 .3em"></i> ' + esc(name);
|
titleEl.innerHTML = '<span class="db-back-link">Datenbank-Explorer</span> <i class="fa fa-chevron-right chevron-separator"></i> ' + esc(name);
|
||||||
|
|
||||||
// Back-Link klickbar
|
// Back-Link klickbar
|
||||||
titleEl.querySelector('.db-back-link').style.cursor = 'pointer';
|
titleEl.querySelector('.db-back-link').classList.add('clickable');
|
||||||
titleEl.querySelector('.db-back-link').addEventListener('click', function() {
|
titleEl.querySelector('.db-back-link').addEventListener('click', function() {
|
||||||
loadTables();
|
loadTables();
|
||||||
});
|
});
|
||||||
@@ -129,7 +129,7 @@ registerPage('db-explorer', {
|
|||||||
data.columns.forEach(function(col) {
|
data.columns.forEach(function(col) {
|
||||||
var th = document.createElement('th');
|
var th = document.createElement('th');
|
||||||
th.textContent = col.name;
|
th.textContent = col.name;
|
||||||
if (col.pk) th.innerHTML += ' <i class="fa fa-key" style="opacity:.4;font-size:.75em"></i>';
|
if (col.pk) th.innerHTML += ' <i class="fa fa-key icon-dim-sm"></i>';
|
||||||
th.title = col.type + (col.notnull ? ' NOT NULL' : '') + (col.pk ? ' PRIMARY KEY' : '');
|
th.title = col.type + (col.notnull ? ' NOT NULL' : '') + (col.pk ? ' PRIMARY KEY' : '');
|
||||||
headerRow.appendChild(th);
|
headerRow.appendChild(th);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ registerPage('settings', {
|
|||||||
|
|
||||||
// Backup nur für Admins
|
// Backup nur für Admins
|
||||||
if (currentUser && currentUser.isAdmin) {
|
if (currentUser && currentUser.isAdmin) {
|
||||||
backupSection.style.display = '';
|
backupSection.hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = loadSettings();
|
const s = loadSettings();
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ fetch('/api/info').then(r => r.json()).then(data => {
|
|||||||
|
|
||||||
function _showEmbeddingWarning() {
|
function _showEmbeddingWarning() {
|
||||||
const { body } = _createModal('⚠️ Embedding-Modell nicht gefunden');
|
const { body } = _createModal('⚠️ Embedding-Modell nicht gefunden');
|
||||||
body.style.lineHeight = '1.7';
|
body.classList.add('lh-relaxed');
|
||||||
body.innerHTML =
|
body.innerHTML =
|
||||||
'<p>Das Embedding-Modell <strong>all-MiniLM-L6-v2</strong> wurde nicht gefunden. ' +
|
'<p>Das Embedding-Modell <strong>all-MiniLM-L6-v2</strong> wurde nicht gefunden. ' +
|
||||||
'Ohne dieses Modell ist die semantische Suche (<code>memory_search</code>) deaktiviert.</p>' +
|
'Ohne dieses Modell ist die semantische Suche (<code>memory_search</code>) deaktiviert.</p>' +
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ function renderToolBoxContent(div, name, inputJson, result, isError, sources) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foldTarget && name !== 'todo_write') {
|
if (foldTarget && name !== 'todo_write') {
|
||||||
header.style.cursor = 'pointer';
|
header.classList.add('clickable');
|
||||||
header.addEventListener('click', () => {
|
header.addEventListener('click', () => {
|
||||||
foldTarget.hidden = !foldTarget.hidden;
|
foldTarget.hidden = !foldTarget.hidden;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user