Loading editor/CMakeLists.txt +1 −0 Changes for editor/CMakeLists.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ add_executable(blogi-editor src/webedit_session.cpp src/webedit_server.cpp src/webedit_api.cpp src/webedit_mcp.cpp src/htmlimport.cpp ) Loading editor/html/index.html +20 −0 Changes for editor/html/index.html: 20 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -330,6 +330,7 @@ <li class="set-nav-item active" data-section="language" data-i18n="Language">Sprache</li> <li class="set-nav-item" data-section="ai" data-i18n="I18N_AI">KI</li> <li class="set-nav-item" data-section="connection" data-i18n="I18N_CONNECTION">Verbindung</li> <li class="set-nav-item" data-section="mcp" data-i18n="I18N_MCP">MCP</li> </ul> </div> <div class="set-content" id="settings-content"> Loading Loading @@ -383,6 +384,25 @@ </div> </div> <!-- MCP API tokens section --> <div id="settings-mcp" class="set-section" style="display:none"> <h4 data-i18n="I18N_MCP">MCP</h4> <p class="hint" data-i18n="I18N_MCP_HINT">Mit einem API-Token können externe MCP-Clients (z.B. Claude Desktop/Code) diesen Editor per Model Context Protocol steuern. Sendet der Client "Authorization: Bearer <Token>" an /mcp.</p> <div class="set-field"> <label data-i18n="I18N_MCP_LABEL">Bezeichnung</label> <input type="text" id="settings-mcp-label" placeholder="z.B. Claude Desktop"> </div> <div class="set-field"> <button id="btn-settings-mcp-create" class="set-save-btn" data-i18n="I18N_MCP_CREATE">Token erzeugen</button> <span id="settings-mcp-status" class="set-status"></span> </div> <div class="set-field" id="settings-mcp-new-token-wrap" style="display:none"> <label data-i18n="I18N_MCP_NEW_TOKEN">Neues Token (jetzt kopieren, wird nicht erneut angezeigt)</label> <input type="text" id="settings-mcp-new-token" readonly onclick="this.select()"> </div> <div id="settings-mcp-list" class="conn-list"></div> </div> <!-- Plugin settings section (loaded dynamically) --> <div id="settings-plugin" class="set-section" style="display:none"> <div id="settings-plugin-content"></div> Loading editor/html/js/api.js +13 −0 Changes for editor/html/js/api.js: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -336,6 +336,19 @@ var EditorApi = (function() { return request('DELETE', '/api/connection/delete/' + id); }, // MCP API tokens getMcpTokens: function() { return request('GET', '/api/mcp/tokens'); }, createMcpToken: function(label) { return request('POST', '/api/mcp/tokens', { label: label }); }, revokeMcpToken: function(id) { return request('DELETE', '/api/mcp/tokens/' + id); }, connectToConnection: function(id) { return request('POST', '/api/connection/connect/' + id, {}).then(function(resp) { if (resp && resp.blogUrl && resp.authid) { Loading editor/html/js/editor.js +65 −0 Changes for editor/html/js/editor.js: 65 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1110,6 +1110,10 @@ document.getElementById('settings-ai-status').textContent = ''; }); document.getElementById('settings-mcp-new-token-wrap').style.display = 'none'; document.getElementById('settings-mcp-label').value = ''; loadMcpTokens(); // Load plugin settings nav items var nav = document.querySelector('#settings-dialog .set-nav'); // Remove previously added plugin nav items Loading Loading @@ -1140,6 +1144,47 @@ document.getElementById('settings-dialog').showModal(); } function loadMcpTokens() { EditorApi.getMcpTokens().then(function(resp) { renderMcpTokenList(resp.tokens || []); }).catch(function() {}); } function renderMcpTokenList(tokens) { var list = document.getElementById('settings-mcp-list'); list.innerHTML = ''; if (tokens.length === 0) { list.innerHTML = '<p class="hint" style="padding:0.5em">' + I18n.t('I18N_MCP_NO_TOKENS', 'Keine Tokens') + '</p>'; return; } tokens.forEach(function(token) { var item = document.createElement('div'); item.className = 'conn-item'; var label = document.createElement('span'); label.textContent = (token.label || I18n.t('I18N_MCP_UNNAMED', '(unbenannt)')) + ' — ' + (token.created || '') + (token.last_used ? ' • ' + I18n.t('I18N_MCP_LAST_USED', 'zuletzt verwendet') + ': ' + token.last_used : ''); item.appendChild(label); var del = document.createElement('button'); del.textContent = '✕'; del.title = I18n.t('I18N_MCP_REVOKE', 'Widerrufen'); del.style.marginLeft = 'auto'; del.addEventListener('click', function(e) { e.stopPropagation(); EditorApi.revokeMcpToken(token.id).then(loadMcpTokens); }); item.appendChild(del); list.appendChild(item); }); } function loadPluginSettingsSection(pluginId) { var contentEl = document.getElementById('settings-plugin-content'); contentEl.innerHTML = '<p class="hint">Lade...</p>'; Loading Loading @@ -1244,6 +1289,26 @@ document.getElementById('settings-dialog').close(); openConnectionManager(); }); // MCP token creation document.getElementById('btn-settings-mcp-create').addEventListener('click', function() { var status = document.getElementById('settings-mcp-status'); var label = document.getElementById('settings-mcp-label').value; status.textContent = I18n.t('I18N_SAVING', 'Saving...'); EditorApi.createMcpToken(label).then(function(resp) { status.textContent = ''; document.getElementById('settings-mcp-label').value = ''; var wrap = document.getElementById('settings-mcp-new-token-wrap'); var tokenInput = document.getElementById('settings-mcp-new-token'); tokenInput.value = resp.token; wrap.style.display = 'block'; tokenInput.select(); loadMcpTokens(); }).catch(function() { status.textContent = I18n.t('I18N_SAVE_FAILED', 'Save failed'); status.className = 'set-status error'; }); }); } // --- AI dialog --- Loading editor/src/webedit_api.cpp +608 −121 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
editor/CMakeLists.txt +1 −0 Changes for editor/CMakeLists.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ add_executable(blogi-editor src/webedit_session.cpp src/webedit_server.cpp src/webedit_api.cpp src/webedit_mcp.cpp src/htmlimport.cpp ) Loading
editor/html/index.html +20 −0 Changes for editor/html/index.html: 20 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -330,6 +330,7 @@ <li class="set-nav-item active" data-section="language" data-i18n="Language">Sprache</li> <li class="set-nav-item" data-section="ai" data-i18n="I18N_AI">KI</li> <li class="set-nav-item" data-section="connection" data-i18n="I18N_CONNECTION">Verbindung</li> <li class="set-nav-item" data-section="mcp" data-i18n="I18N_MCP">MCP</li> </ul> </div> <div class="set-content" id="settings-content"> Loading Loading @@ -383,6 +384,25 @@ </div> </div> <!-- MCP API tokens section --> <div id="settings-mcp" class="set-section" style="display:none"> <h4 data-i18n="I18N_MCP">MCP</h4> <p class="hint" data-i18n="I18N_MCP_HINT">Mit einem API-Token können externe MCP-Clients (z.B. Claude Desktop/Code) diesen Editor per Model Context Protocol steuern. Sendet der Client "Authorization: Bearer <Token>" an /mcp.</p> <div class="set-field"> <label data-i18n="I18N_MCP_LABEL">Bezeichnung</label> <input type="text" id="settings-mcp-label" placeholder="z.B. Claude Desktop"> </div> <div class="set-field"> <button id="btn-settings-mcp-create" class="set-save-btn" data-i18n="I18N_MCP_CREATE">Token erzeugen</button> <span id="settings-mcp-status" class="set-status"></span> </div> <div class="set-field" id="settings-mcp-new-token-wrap" style="display:none"> <label data-i18n="I18N_MCP_NEW_TOKEN">Neues Token (jetzt kopieren, wird nicht erneut angezeigt)</label> <input type="text" id="settings-mcp-new-token" readonly onclick="this.select()"> </div> <div id="settings-mcp-list" class="conn-list"></div> </div> <!-- Plugin settings section (loaded dynamically) --> <div id="settings-plugin" class="set-section" style="display:none"> <div id="settings-plugin-content"></div> Loading
editor/html/js/api.js +13 −0 Changes for editor/html/js/api.js: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -336,6 +336,19 @@ var EditorApi = (function() { return request('DELETE', '/api/connection/delete/' + id); }, // MCP API tokens getMcpTokens: function() { return request('GET', '/api/mcp/tokens'); }, createMcpToken: function(label) { return request('POST', '/api/mcp/tokens', { label: label }); }, revokeMcpToken: function(id) { return request('DELETE', '/api/mcp/tokens/' + id); }, connectToConnection: function(id) { return request('POST', '/api/connection/connect/' + id, {}).then(function(resp) { if (resp && resp.blogUrl && resp.authid) { Loading
editor/html/js/editor.js +65 −0 Changes for editor/html/js/editor.js: 65 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1110,6 +1110,10 @@ document.getElementById('settings-ai-status').textContent = ''; }); document.getElementById('settings-mcp-new-token-wrap').style.display = 'none'; document.getElementById('settings-mcp-label').value = ''; loadMcpTokens(); // Load plugin settings nav items var nav = document.querySelector('#settings-dialog .set-nav'); // Remove previously added plugin nav items Loading Loading @@ -1140,6 +1144,47 @@ document.getElementById('settings-dialog').showModal(); } function loadMcpTokens() { EditorApi.getMcpTokens().then(function(resp) { renderMcpTokenList(resp.tokens || []); }).catch(function() {}); } function renderMcpTokenList(tokens) { var list = document.getElementById('settings-mcp-list'); list.innerHTML = ''; if (tokens.length === 0) { list.innerHTML = '<p class="hint" style="padding:0.5em">' + I18n.t('I18N_MCP_NO_TOKENS', 'Keine Tokens') + '</p>'; return; } tokens.forEach(function(token) { var item = document.createElement('div'); item.className = 'conn-item'; var label = document.createElement('span'); label.textContent = (token.label || I18n.t('I18N_MCP_UNNAMED', '(unbenannt)')) + ' — ' + (token.created || '') + (token.last_used ? ' • ' + I18n.t('I18N_MCP_LAST_USED', 'zuletzt verwendet') + ': ' + token.last_used : ''); item.appendChild(label); var del = document.createElement('button'); del.textContent = '✕'; del.title = I18n.t('I18N_MCP_REVOKE', 'Widerrufen'); del.style.marginLeft = 'auto'; del.addEventListener('click', function(e) { e.stopPropagation(); EditorApi.revokeMcpToken(token.id).then(loadMcpTokens); }); item.appendChild(del); list.appendChild(item); }); } function loadPluginSettingsSection(pluginId) { var contentEl = document.getElementById('settings-plugin-content'); contentEl.innerHTML = '<p class="hint">Lade...</p>'; Loading Loading @@ -1244,6 +1289,26 @@ document.getElementById('settings-dialog').close(); openConnectionManager(); }); // MCP token creation document.getElementById('btn-settings-mcp-create').addEventListener('click', function() { var status = document.getElementById('settings-mcp-status'); var label = document.getElementById('settings-mcp-label').value; status.textContent = I18n.t('I18N_SAVING', 'Saving...'); EditorApi.createMcpToken(label).then(function(resp) { status.textContent = ''; document.getElementById('settings-mcp-label').value = ''; var wrap = document.getElementById('settings-mcp-new-token-wrap'); var tokenInput = document.getElementById('settings-mcp-new-token'); tokenInput.value = resp.token; wrap.style.display = 'block'; tokenInput.select(); loadMcpTokens(); }).catch(function() { status.textContent = I18n.t('I18N_SAVE_FAILED', 'Save failed'); status.className = 'set-status error'; }); }); } // --- AI dialog --- Loading
editor/src/webedit_api.cpp +608 −121 File changed.Preview size limit exceeded, changes collapsed. Show changes