feat: Editier-Button in Template-Karten hinzugefügt mit Modal (Speichern/Abbrechen)
- Bearbeiten-Button in jeder Template-Karte - Editier-Modal mit Save/Abbrechen-Funktionalität - PUT-Endpoint in serve.py zum Speichern bearbeiteter Dateien
This commit is contained in:
parent
8e01dd75a1
commit
83117d0de8
2 changed files with 107 additions and 0 deletions
|
|
@ -427,6 +427,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Modal -->
|
||||||
|
<div class="modal-overlay" id="edit-modal">
|
||||||
|
<div class="modal" style="max-width: 800px;">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 id="edit-title">Template bearbeiten</h2>
|
||||||
|
<button class="modal-close" onclick="closeEditModal()">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<textarea id="edit-content" style="width: 100%; min-height: 300px; background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border); border-radius: 4px; font-family: var(--mono); font-size: 13px; padding: 10px;" spellcheck="false"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="modal-actions">
|
||||||
|
<button class="btn btn-primary" onclick="saveEditedContent()">Speichern</button>
|
||||||
|
<button class="btn" onclick="closeEditModal()">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Toast -->
|
<!-- Toast -->
|
||||||
<div class="toast" id="toast"></div>
|
<div class="toast" id="toast"></div>
|
||||||
|
|
||||||
|
|
@ -485,6 +502,53 @@ $ python web/serve.py</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let allTemplates = [];
|
let allTemplates = [];
|
||||||
|
let currentEditTemplate = null;
|
||||||
|
|
||||||
|
// Edit Modal Funktionen
|
||||||
|
function closeEditModal() {
|
||||||
|
document.getElementById('edit-modal').classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
function editModalContent(path) {
|
||||||
|
currentEditTemplate = path;
|
||||||
|
const title = path.split('/').pop();
|
||||||
|
document.getElementById('edit-title').textContent = `Template bearbeiten: ${title}`;
|
||||||
|
|
||||||
|
// Inhalt laden
|
||||||
|
fetch(path).then(r => r.text()).then(content => {
|
||||||
|
document.getElementById('edit-content').value = content;
|
||||||
|
document.getElementById('edit-modal').classList.add('active');
|
||||||
|
}).catch(e => {
|
||||||
|
showToast(`✗ Fehler beim Laden: ${e.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveEditedContent() {
|
||||||
|
if (!currentEditTemplate) return;
|
||||||
|
|
||||||
|
const content = document.getElementById('edit-content').value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(currentEditTemplate, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/plain'
|
||||||
|
},
|
||||||
|
body: content
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
showToast('✓ Änderungen gespeichert');
|
||||||
|
closeEditModal();
|
||||||
|
closeModal();
|
||||||
|
showModal(currentEditTemplate.split('/').pop(), content);
|
||||||
|
} else {
|
||||||
|
throw new Error(`HTTP ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showToast(`✗ Fehler beim Speichern: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Modal-Funktionen
|
// Modal-Funktionen
|
||||||
function showModal(title, content) {
|
function showModal(title, content) {
|
||||||
|
|
@ -648,6 +712,7 @@ $ python web/serve.py</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn btn-icon" onclick="viewTemplate('${t.path}')">Anzeigen</button>
|
<button class="btn btn-icon" onclick="viewTemplate('${t.path}')">Anzeigen</button>
|
||||||
|
<button class="btn btn-icon" onclick="editModalContent('${t.path}')">📝 Bearbeiten</button>
|
||||||
<button class="btn btn-icon" onclick="copyContent('${t.path}')">Inhalt kopieren</button>
|
<button class="btn btn-icon" onclick="copyContent('${t.path}')">Inhalt kopieren</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
42
web/serve.py
42
web/serve.py
|
|
@ -29,6 +29,48 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, directory=DIRECTORY, **kwargs)
|
super().__init__(*args, directory=DIRECTORY, **kwargs)
|
||||||
|
|
||||||
|
def do_PUT(self):
|
||||||
|
# Nur PUT auf /templates/* Pfade erlauben
|
||||||
|
if not self.path.startswith('/templates'):
|
||||||
|
self.send_error(403, "Method not allowed for this path")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Pfad relativ zur ROOT_DIR konstruieren
|
||||||
|
rel_path = self.path[1:] # '/templates/system/test.json' → 'templates/system/test.json'
|
||||||
|
file_path = os.path.join(ROOT_DIR, rel_path)
|
||||||
|
|
||||||
|
# Verzeichnis prüfen - muss existieren
|
||||||
|
file_dir = os.path.dirname(file_path)
|
||||||
|
if not os.path.exists(file_dir) or not os.path.isdir(file_dir):
|
||||||
|
self.send_error(404, "Directory not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Content-Type prüfen
|
||||||
|
content_type = self.headers.get('Content-Type', '')
|
||||||
|
if 'text/plain' not in content_type and not content_type.startswith('text/'):
|
||||||
|
self.send_error(400, "Unsupported content type")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Inhalt lesen und speichern
|
||||||
|
content_length = int(self.headers.get('Content-Length', 0))
|
||||||
|
if content_length <= 0:
|
||||||
|
self.send_error(400, "No content provided")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_content = self.rfile.read(content_length)
|
||||||
|
|
||||||
|
# Datei schreiben
|
||||||
|
with open(file_path, 'wb') as f:
|
||||||
|
f.write(file_content)
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b"File saved successfully")
|
||||||
|
except Exception as e:
|
||||||
|
self.send_error(500, f"Failed to save file: {e}")
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
# Für Root-Pfad: index.html servieren
|
# Für Root-Pfad: index.html servieren
|
||||||
if self.path == '/' or self.path == '/index.html':
|
if self.path == '/' or self.path == '/index.html':
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue