Loading editor/html/css/editor.css +24 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,30 @@ dialog label { } /* Document list in open dialog */ .doc-group-header { display: flex; align-items: center; padding: 6px 8px; margin-top: 8px; margin-bottom: 2px; font-weight: 600; font-size: 13px; color: var(--text-secondary); cursor: pointer; user-select: none; border-radius: 4px; } .doc-group-header:hover { background: var(--bg-hover); } .doc-group-header::before { content: '\25BE'; margin-right: 6px; font-size: 10px; transition: transform 0.15s; } .doc-group-header.collapsed::before { transform: rotate(-90deg); } .doc-item { display: flex; align-items: center; Loading editor/html/index.html +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ <dialog id="save-dialog"> <h3 data-i18n="I18N_SAVE_TPL_TITLE">Dokument speichern</h3> <label><span data-i18n="I18N_GROUP">Gruppe</span>: <input type="text" id="save-group" data-i18n-placeholder="I18N_GROUP_PLACEHOLDER" placeholder="z.B. Vorlagen/Blog"></label> <label><span data-i18n="I18N_TPL_NAME_LABEL">Name</span>: <input type="text" id="save-name" data-i18n-placeholder="I18N_TPL_NAME_PLACEHOLDER" placeholder="Dokumentname"></label> <div class="dialog-actions"> <button id="btn-save-confirm" data-i18n="I18N_SAVE">Speichern</button> Loading editor/html/js/api.js +2 −2 Original line number Diff line number Diff line Loading @@ -124,8 +124,8 @@ var EditorApi = (function() { return request('POST', '/api/document/import-xml', { xml: xml }); }, saveDocument: function(name) { return request('POST', '/api/document/save', { name: name }); saveDocument: function(name, group) { return request('POST', '/api/document/save', { name: name, group: group || '' }); }, listDocuments: function() { Loading editor/html/js/editor.js +98 −54 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ var plugins = []; var currentDocId = ''; var currentDocGroup = ''; // --- Initialize --- Loading Loading @@ -122,10 +123,12 @@ if (name === 'Untitled') { var dialog = document.getElementById('save-dialog'); document.getElementById('save-name').value = ''; document.getElementById('save-group').value = currentDocGroup || ''; dialog.showModal(); } else { EditorApi.saveDocument(name).then(function(resp) { EditorApi.saveDocument(name, currentDocGroup).then(function(resp) { document.getElementById('doc-name').textContent = resp.name; currentDocGroup = resp.group || ''; }); } }); Loading Loading @@ -243,8 +246,10 @@ document.getElementById('btn-save-confirm').addEventListener('click', function() { var name = document.getElementById('save-name').value.trim(); if (!name) return; EditorApi.saveDocument(name).then(function(resp) { var group = document.getElementById('save-group').value.trim(); EditorApi.saveDocument(name, group).then(function(resp) { document.getElementById('doc-name').textContent = resp.name; currentDocGroup = resp.group || ''; document.getElementById('save-dialog').close(); }); }); Loading Loading @@ -333,8 +338,47 @@ return; } // Group by folder var groups = {}; for (var i = 0; i < documents.length; i++) { var doc = documents[i]; var g = documents[i].group || ''; if (!groups[g]) groups[g] = []; groups[g].push(documents[i]); } var groupNames = Object.keys(groups).sort(); for (var gi = 0; gi < groupNames.length; gi++) { var groupName = groupNames[gi]; var docs = groups[groupName]; if (groupName) { var groupHeader = document.createElement('div'); groupHeader.className = 'doc-group-header'; groupHeader.innerHTML = '📁 ' + groupName; groupHeader.addEventListener('click', function() { var container = this.nextElementSibling; var collapsed = container.style.display === 'none'; container.style.display = collapsed ? '' : 'none'; this.classList.toggle('collapsed', !collapsed); }); list.appendChild(groupHeader); } var groupContainer = document.createElement('div'); groupContainer.className = 'doc-group-items'; if (groupName) groupContainer.style.paddingLeft = '12px'; for (var i = 0; i < docs.length; i++) { var doc = docs[i]; groupContainer.appendChild(createDocItem(doc)); } list.appendChild(groupContainer); } } function createDocItem(doc) { var item = document.createElement('div'); item.className = 'doc-item'; Loading Loading @@ -387,7 +431,8 @@ item.setAttribute('data-id', doc.id); item.addEventListener('click', function() { var id = this.getAttribute('data-id'); EditorApi.loadDocument(id).then(function() { EditorApi.loadDocument(id).then(function(resp) { currentDocGroup = resp.group || ''; document.getElementById('open-dialog').close(); DocumentTree.clearSelection(); PropertiesPanel.clear(); Loading @@ -395,8 +440,7 @@ }); }); list.appendChild(item); } return item; } // --- Revisions --- Loading editor/src/webedit_api.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -1060,6 +1060,7 @@ void webedit::Api::handleLoadDocument(libhttppp::HttpRequest &curreq, json_object_object_add(resp, "status", json_object_new_string("ok")); json_object_object_add(resp, "id", json_object_new_string(docId.c_str())); json_object_object_add(resp, "name", json_object_new_string(name.c_str())); json_object_object_add(resp, "group", json_object_new_string(group.c_str())); sendJson(curreq, resp); json_object_put(resp); } Loading Loading
editor/html/css/editor.css +24 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,30 @@ dialog label { } /* Document list in open dialog */ .doc-group-header { display: flex; align-items: center; padding: 6px 8px; margin-top: 8px; margin-bottom: 2px; font-weight: 600; font-size: 13px; color: var(--text-secondary); cursor: pointer; user-select: none; border-radius: 4px; } .doc-group-header:hover { background: var(--bg-hover); } .doc-group-header::before { content: '\25BE'; margin-right: 6px; font-size: 10px; transition: transform 0.15s; } .doc-group-header.collapsed::before { transform: rotate(-90deg); } .doc-item { display: flex; align-items: center; Loading
editor/html/index.html +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ <dialog id="save-dialog"> <h3 data-i18n="I18N_SAVE_TPL_TITLE">Dokument speichern</h3> <label><span data-i18n="I18N_GROUP">Gruppe</span>: <input type="text" id="save-group" data-i18n-placeholder="I18N_GROUP_PLACEHOLDER" placeholder="z.B. Vorlagen/Blog"></label> <label><span data-i18n="I18N_TPL_NAME_LABEL">Name</span>: <input type="text" id="save-name" data-i18n-placeholder="I18N_TPL_NAME_PLACEHOLDER" placeholder="Dokumentname"></label> <div class="dialog-actions"> <button id="btn-save-confirm" data-i18n="I18N_SAVE">Speichern</button> Loading
editor/html/js/api.js +2 −2 Original line number Diff line number Diff line Loading @@ -124,8 +124,8 @@ var EditorApi = (function() { return request('POST', '/api/document/import-xml', { xml: xml }); }, saveDocument: function(name) { return request('POST', '/api/document/save', { name: name }); saveDocument: function(name, group) { return request('POST', '/api/document/save', { name: name, group: group || '' }); }, listDocuments: function() { Loading
editor/html/js/editor.js +98 −54 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ var plugins = []; var currentDocId = ''; var currentDocGroup = ''; // --- Initialize --- Loading Loading @@ -122,10 +123,12 @@ if (name === 'Untitled') { var dialog = document.getElementById('save-dialog'); document.getElementById('save-name').value = ''; document.getElementById('save-group').value = currentDocGroup || ''; dialog.showModal(); } else { EditorApi.saveDocument(name).then(function(resp) { EditorApi.saveDocument(name, currentDocGroup).then(function(resp) { document.getElementById('doc-name').textContent = resp.name; currentDocGroup = resp.group || ''; }); } }); Loading Loading @@ -243,8 +246,10 @@ document.getElementById('btn-save-confirm').addEventListener('click', function() { var name = document.getElementById('save-name').value.trim(); if (!name) return; EditorApi.saveDocument(name).then(function(resp) { var group = document.getElementById('save-group').value.trim(); EditorApi.saveDocument(name, group).then(function(resp) { document.getElementById('doc-name').textContent = resp.name; currentDocGroup = resp.group || ''; document.getElementById('save-dialog').close(); }); }); Loading Loading @@ -333,8 +338,47 @@ return; } // Group by folder var groups = {}; for (var i = 0; i < documents.length; i++) { var doc = documents[i]; var g = documents[i].group || ''; if (!groups[g]) groups[g] = []; groups[g].push(documents[i]); } var groupNames = Object.keys(groups).sort(); for (var gi = 0; gi < groupNames.length; gi++) { var groupName = groupNames[gi]; var docs = groups[groupName]; if (groupName) { var groupHeader = document.createElement('div'); groupHeader.className = 'doc-group-header'; groupHeader.innerHTML = '📁 ' + groupName; groupHeader.addEventListener('click', function() { var container = this.nextElementSibling; var collapsed = container.style.display === 'none'; container.style.display = collapsed ? '' : 'none'; this.classList.toggle('collapsed', !collapsed); }); list.appendChild(groupHeader); } var groupContainer = document.createElement('div'); groupContainer.className = 'doc-group-items'; if (groupName) groupContainer.style.paddingLeft = '12px'; for (var i = 0; i < docs.length; i++) { var doc = docs[i]; groupContainer.appendChild(createDocItem(doc)); } list.appendChild(groupContainer); } } function createDocItem(doc) { var item = document.createElement('div'); item.className = 'doc-item'; Loading Loading @@ -387,7 +431,8 @@ item.setAttribute('data-id', doc.id); item.addEventListener('click', function() { var id = this.getAttribute('data-id'); EditorApi.loadDocument(id).then(function() { EditorApi.loadDocument(id).then(function(resp) { currentDocGroup = resp.group || ''; document.getElementById('open-dialog').close(); DocumentTree.clearSelection(); PropertiesPanel.clear(); Loading @@ -395,8 +440,7 @@ }); }); list.appendChild(item); } return item; } // --- Revisions --- Loading
editor/src/webedit_api.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -1060,6 +1060,7 @@ void webedit::Api::handleLoadDocument(libhttppp::HttpRequest &curreq, json_object_object_add(resp, "status", json_object_new_string("ok")); json_object_object_add(resp, "id", json_object_new_string(docId.c_str())); json_object_object_add(resp, "name", json_object_new_string(name.c_str())); json_object_object_add(resp, "group", json_object_new_string(group.c_str())); sendJson(curreq, resp); json_object_put(resp); } Loading