refactor(frontend): Duplikate in JS eliminieren – Runde 2
Neue Helper-Funktionen: - _openCardMenu(trigger, dropdown): Card-Menü-Positionierung (4x in dashboard.js dedupliziert) - _createModal(title, extraClasses): Modal-Boilerplate (3 Modals in modals.js dedupliziert) - _openPickerModal(title, items, currentId, onSelect, opts): Picker-Modal (Agent + Session zusammengeführt) - createMDE(element, opts): EasyMDE-Initialisierung (3x in agent/session/profile-page dedupliziert) Weitere Bereinigungen: - _formatReplyTimestamp() entfernt, durch _formatTimestamp() ersetzt (reply.js + chat.js) - showFormMessage/showPageMessage in admin-page.js durch showToast() ersetzt - Inline-Nachrichten (profileMessage, profilePasswordMessage, adminMessage, adminFormMessage) durch Toast-Notifications ersetzt, zugehörige HTML-Elemente entfernt - profile-page.js: messageDiv/passwordMessageDiv-Logik durch showToast() ersetzt 11 Dateien, -210 Zeilen netto
This commit is contained in:
1 parent
b56b83ad1e
commit
1a2c407538
11 files changed
+177
-387
No files matched your search
+100
-107
@@ -1,3 +1,43 @@
|
||||
// ── Modal Helper ──
|
||||
|
||||
function _createModal(titleText, extraClasses) {
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'sp-overlay' + (extraClasses && extraClasses.overlay ? ' ' + extraClasses.overlay : '');
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'sp-modal' + (extraClasses && extraClasses.modal ? ' ' + extraClasses.modal : '');
|
||||
|
||||
const header = document.createElement('div');
|
||||
header.className = 'sp-header';
|
||||
const title = document.createElement('span');
|
||||
title.textContent = titleText;
|
||||
const closeBtn = document.createElement('button');
|
||||
closeBtn.innerHTML = '<i class="fa fa-times"></i>';
|
||||
closeBtn.className = 'sp-close icon-btn';
|
||||
header.appendChild(title);
|
||||
header.appendChild(closeBtn);
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.className = 'sp-body' + (extraClasses && extraClasses.body ? ' ' + extraClasses.body : '');
|
||||
|
||||
modal.appendChild(header);
|
||||
modal.appendChild(body);
|
||||
overlay.appendChild(modal);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
const close = () => overlay.remove();
|
||||
closeBtn.addEventListener('click', close);
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) close();
|
||||
});
|
||||
const onKey = (e) => {
|
||||
if (e.key === 'Escape') { close(); document.removeEventListener('keydown', onKey); }
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
|
||||
return { overlay, modal, body, close };
|
||||
}
|
||||
|
||||
// ── System-Prompt Modal ──
|
||||
|
||||
function _renderSystemPromptBlocks(container, blocks) {
|
||||
@@ -24,47 +64,9 @@ function _renderSystemPromptBlocks(container, blocks) {
|
||||
}
|
||||
|
||||
async function showSystemPromptModal(sessionId) {
|
||||
// Overlay
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'sp-overlay';
|
||||
|
||||
// Modal
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'sp-modal';
|
||||
|
||||
// Header
|
||||
const header = document.createElement('div');
|
||||
header.className = 'sp-header';
|
||||
const title = document.createElement('span');
|
||||
title.textContent = 'System-Prompt';
|
||||
const closeBtn = document.createElement('button');
|
||||
closeBtn.innerHTML = '<i class="fa fa-times"></i>';
|
||||
closeBtn.className = 'sp-close icon-btn';
|
||||
header.appendChild(title);
|
||||
header.appendChild(closeBtn);
|
||||
|
||||
// Body
|
||||
const body = document.createElement('div');
|
||||
body.className = 'sp-body markdown';
|
||||
const { body } = _createModal('System-Prompt', { body: 'markdown' });
|
||||
body.innerHTML = '<div class="sp-loading">Laden...</div>';
|
||||
|
||||
modal.appendChild(header);
|
||||
modal.appendChild(body);
|
||||
overlay.appendChild(modal);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// Schließen
|
||||
const close = () => overlay.remove();
|
||||
closeBtn.addEventListener('click', close);
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) close();
|
||||
});
|
||||
const onKey = (e) => {
|
||||
if (e.key === 'Escape') { close(); document.removeEventListener('keydown', onKey); }
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
|
||||
// Laden
|
||||
try {
|
||||
const blocks = await apiGetSystemPromptBlocks(sessionId, typeof _planModeActive !== 'undefined' && _planModeActive);
|
||||
body.innerHTML = '';
|
||||
@@ -77,30 +79,11 @@ async function showSystemPromptModal(sessionId) {
|
||||
// ── Command Output Modal ──
|
||||
|
||||
function showCommandOutputModal(name, command, result) {
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'sp-overlay';
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'sp-modal cmd-output-modal';
|
||||
|
||||
// Header
|
||||
const header = document.createElement('div');
|
||||
header.className = 'sp-header';
|
||||
const title = document.createElement('span');
|
||||
title.textContent = name;
|
||||
const closeBtn = document.createElement('button');
|
||||
closeBtn.innerHTML = '<i class="fa fa-times"></i>';
|
||||
closeBtn.className = 'sp-close icon-btn';
|
||||
header.appendChild(title);
|
||||
header.appendChild(closeBtn);
|
||||
|
||||
// Body
|
||||
const body = document.createElement('div');
|
||||
body.className = 'sp-body';
|
||||
const { body } = _createModal(name, { modal: 'cmd-output-modal' });
|
||||
|
||||
const exitCode = result.exitCode != null ? result.exitCode : '?';
|
||||
const isError = exitCode !== 0;
|
||||
const statusText = result.status === 'timeout' ? 'Timeout' : (isError ? `Exit ${exitCode}` : `Exit ${exitCode}`);
|
||||
const statusText = result.status === 'timeout' ? 'Timeout' : `Exit ${exitCode}`;
|
||||
|
||||
const meta = document.createElement('div');
|
||||
meta.className = 'cmd-output-meta';
|
||||
@@ -111,72 +94,82 @@ function showCommandOutputModal(name, command, result) {
|
||||
output.className = 'cmd-output-content';
|
||||
output.textContent = result.output || '(kein Output)';
|
||||
body.appendChild(output);
|
||||
|
||||
modal.appendChild(header);
|
||||
modal.appendChild(body);
|
||||
overlay.appendChild(modal);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// Schließen
|
||||
const close = () => overlay.remove();
|
||||
closeBtn.addEventListener('click', close);
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) close();
|
||||
});
|
||||
const onKey = (e) => {
|
||||
if (e.key === 'Escape') { close(); document.removeEventListener('keydown', onKey); }
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
}
|
||||
|
||||
// ── Krea Image Preview Modal ──
|
||||
|
||||
function showKreaImageModal(title, fullUrl) {
|
||||
var overlay = document.createElement('div');
|
||||
overlay.className = 'sp-overlay krea-overlay';
|
||||
|
||||
var modal = document.createElement('div');
|
||||
modal.className = 'sp-modal krea-modal';
|
||||
|
||||
// Header
|
||||
var header = document.createElement('div');
|
||||
header.className = 'sp-header';
|
||||
var titleEl = document.createElement('span');
|
||||
titleEl.textContent = title;
|
||||
var closeBtn = document.createElement('button');
|
||||
closeBtn.innerHTML = '<i class="fa fa-times"></i>';
|
||||
closeBtn.className = 'sp-close icon-btn';
|
||||
header.appendChild(titleEl);
|
||||
header.appendChild(closeBtn);
|
||||
|
||||
// Body
|
||||
var body = document.createElement('div');
|
||||
body.className = 'sp-body krea-modal-body';
|
||||
function showKreaImageModal(titleText, fullUrl) {
|
||||
const { body } = _createModal(titleText, { overlay: 'krea-overlay', modal: 'krea-modal', body: 'krea-modal-body' });
|
||||
|
||||
var img = document.createElement('img');
|
||||
img.src = fullUrl;
|
||||
img.className = 'krea-modal-image';
|
||||
img.alt = title;
|
||||
img.alt = titleText;
|
||||
img.addEventListener('error', function() {
|
||||
body.innerHTML = '<div class="sp-loading" style="color:var(--dangerous)">Bild konnte nicht geladen werden</div>';
|
||||
});
|
||||
|
||||
body.appendChild(img);
|
||||
}
|
||||
|
||||
// ── Picker Modal Helper ──
|
||||
|
||||
function _openPickerModal(title, items, currentId, onSelect, options) {
|
||||
options = options || {};
|
||||
const noneLabel = options.noneLabel || 'Keine Auswahl';
|
||||
const noneIcon = options.noneIcon || 'fa-ban';
|
||||
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'agent-picker-overlay';
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'agent-picker-modal';
|
||||
|
||||
const header = document.createElement('div');
|
||||
header.className = 'agent-picker-header';
|
||||
header.innerHTML = `<span>${esc(title)}</span><button class="icon-btn agent-picker-close"><i class="fa fa-times"></i></button>`;
|
||||
modal.appendChild(header);
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.className = 'agent-picker-body';
|
||||
|
||||
// "Keine" Option
|
||||
const noneCard = document.createElement('div');
|
||||
noneCard.className = 'card agent-picker-item' + (!currentId ? ' selected' : '');
|
||||
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-body">
|
||||
<div class="card-title-row">
|
||||
<span class="card-title">${esc(noneLabel)}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
noneCard.addEventListener('click', () => {
|
||||
onSelect(null);
|
||||
overlay.remove();
|
||||
});
|
||||
body.appendChild(noneCard);
|
||||
|
||||
// Items
|
||||
for (const item of items) {
|
||||
const cardEl = options.buildCard(item);
|
||||
cardEl.classList.add('agent-picker-item');
|
||||
if (item._pickerId === currentId) cardEl.classList.add('selected');
|
||||
cardEl.addEventListener('click', () => {
|
||||
onSelect(item._pickerId);
|
||||
overlay.remove();
|
||||
});
|
||||
body.appendChild(cardEl);
|
||||
}
|
||||
|
||||
modal.appendChild(body);
|
||||
overlay.appendChild(modal);
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// Schließen
|
||||
var close = function() { overlay.remove(); };
|
||||
closeBtn.addEventListener('click', close);
|
||||
overlay.addEventListener('click', function(e) {
|
||||
if (e.target === overlay) close();
|
||||
header.querySelector('.agent-picker-close').addEventListener('click', () => overlay.remove());
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) overlay.remove();
|
||||
});
|
||||
var onKey = function(e) {
|
||||
if (e.key === 'Escape') { close(); document.removeEventListener('keydown', onKey); }
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
}
|
||||
|
||||
// Event-Delegation für Krea-Thumbnails im Chat
|
||||
|
||||
Reference in new issue
Block a user