✅ Frontend-Verbesserungen: - WebDAV-Integration für direktes Template-Bearbeiten - 'In Word öffnen' Button für ms-word: URLs - Verbesserte Template-Karten mit Tag-Informationen - WebDAV-Info-Sektion mit Anleitungen - Korrigierte API-Endpunkte für docxtemplater 🔧 Template-Updates: - Alle Templates auf docxtemplater-Syntax aktualisiert - create-*-fixed.js Scripts für korrekte {tag} Syntax - Entfernt alte ++tag++ und ++INS++ Syntax - Neue create-new-table-template.js für echte Loops 🌐 WebDAV-Features: - Direkter Template-Download über /webdav/templates/ - Template-Bearbeitung in Word möglich - Automatische Speicherung über WebDAV - Fallback auf Download bei Word-Problemen 📊 Template-Syntax-Migration: - {variable} statt ++variable++ - {#array}{field}{/array} statt ++INS array++ - Echte dynamische Tabellen ohne fixe Indizes - Verbesserte Tag-Erkennung und Analyse
386 lines
14 KiB
HTML
386 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>📄 Template Management - DOCX Server</title>
|
||
<style>
|
||
body {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
margin: 0;
|
||
padding: 20px;
|
||
background-color: #f5f5f5;
|
||
}
|
||
.container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
background: white;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
overflow: hidden;
|
||
}
|
||
.header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 30px;
|
||
text-align: center;
|
||
}
|
||
.header h1 {
|
||
margin: 0;
|
||
font-size: 2.5em;
|
||
}
|
||
.header p {
|
||
margin: 10px 0 0 0;
|
||
opacity: 0.9;
|
||
}
|
||
.webdav-info {
|
||
background: #e3f2fd;
|
||
border: 1px solid #1976d2;
|
||
border-radius: 5px;
|
||
padding: 15px;
|
||
margin: 20px 0;
|
||
}
|
||
.webdav-info h3 {
|
||
margin: 0 0 10px 0;
|
||
color: #1976d2;
|
||
}
|
||
.webdav-info code {
|
||
background: #fff;
|
||
padding: 2px 5px;
|
||
border-radius: 3px;
|
||
font-family: monospace;
|
||
}
|
||
.content {
|
||
padding: 30px;
|
||
}
|
||
.templates-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
}
|
||
.template-card {
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
background: #fafafa;
|
||
transition: transform 0.2s, box-shadow 0.2s;
|
||
}
|
||
.template-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||
}
|
||
.template-name {
|
||
font-size: 1.2em;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 10px;
|
||
}
|
||
.template-info {
|
||
color: #666;
|
||
font-size: 0.9em;
|
||
margin-bottom: 15px;
|
||
}
|
||
.action-buttons {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
.btn {
|
||
padding: 8px 16px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
font-size: 0.9em;
|
||
transition: background-color 0.2s;
|
||
}
|
||
.btn-analyze {
|
||
background-color: #17a2b8;
|
||
color: white;
|
||
}
|
||
.btn-analyze:hover {
|
||
background-color: #138496;
|
||
}
|
||
.btn-test {
|
||
background-color: #28a745;
|
||
color: white;
|
||
}
|
||
.btn-test:hover {
|
||
background-color: #218838;
|
||
}
|
||
.btn-demo {
|
||
background-color: #ff6b35;
|
||
color: white;
|
||
font-weight: bold;
|
||
}
|
||
.btn-demo:hover {
|
||
background-color: #e55a2b;
|
||
}
|
||
.btn-word {
|
||
background-color: #0066cc;
|
||
color: white;
|
||
}
|
||
.btn-word:hover {
|
||
background-color: #0052a3;
|
||
}
|
||
.btn-webdav {
|
||
background-color: #6c757d;
|
||
color: white;
|
||
}
|
||
.btn-webdav:hover {
|
||
background-color: #5a6268;
|
||
}
|
||
.loading {
|
||
text-align: center;
|
||
padding: 40px;
|
||
color: #666;
|
||
}
|
||
.info-section {
|
||
background-color: #e3f2fd;
|
||
border-left: 4px solid #2196f3;
|
||
padding: 15px;
|
||
margin: 20px 0;
|
||
border-radius: 4px;
|
||
}
|
||
.refresh-btn {
|
||
background-color: #007bff;
|
||
color: white;
|
||
padding: 10px 20px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
margin-bottom: 20px;
|
||
}
|
||
.refresh-btn:hover {
|
||
background-color: #0056b3;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>📄 Template Management</h1>
|
||
<p>DOCX Template Server - Analyse, Test und Verwaltung</p>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<button class="refresh-btn" onclick="loadTemplates()">🔄 Templates neu laden</button>
|
||
|
||
<div class="webdav-info">
|
||
<h3>🌐 WebDAV Template-Bearbeitung</h3>
|
||
<p><strong>Template direkt in Word bearbeiten:</strong></p>
|
||
<ul>
|
||
<li>Klicken Sie auf <strong>"📝 In Word öffnen"</strong> bei einem Template</li>
|
||
<li>Word öffnet das Template direkt vom Server</li>
|
||
<li>Änderungen werden automatisch gespeichert</li>
|
||
</ul>
|
||
<p><strong>WebDAV-URLs:</strong></p>
|
||
<ul>
|
||
<li>Templates: <code>${window.location.origin}/webdav/templates/</code></li>
|
||
<li>Generierte Dateien: <code>${window.location.origin}/webdav/output/</code></li>
|
||
</ul>
|
||
<p><em>💡 Tipp: Sie können diese URLs auch als Netzlaufwerk in Windows einbinden!</em></p>
|
||
</div>
|
||
|
||
<div class="info-section">
|
||
<h3>🚀 Neue Features:</h3>
|
||
<ul>
|
||
<li><strong><EFBFBD> One-Click Demo:</strong> Analyse + Demo-Dokument in einem Schritt</li>
|
||
<li><strong><EFBFBD>📊 Analysieren:</strong> Alle Template-Tags automatisch erkennen</li>
|
||
<li><strong>🎲 Testen:</strong> Test-Dokument mit Zufallsdaten erstellen</li>
|
||
<li><strong>📝 MS Word:</strong> Direkt in Word öffnen und bearbeiten</li>
|
||
<li><strong>🌐 WebDAV:</strong> Browser-basierte Dateiverwaltung</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div id="loading" class="loading">
|
||
🔄 Lade Templates...
|
||
</div>
|
||
|
||
<div id="templates-container" style="display: none;">
|
||
<h2>📁 Verfügbare Templates (<span id="template-count">0</span>)</h2>
|
||
<div id="templates-grid" class="templates-grid">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
async function loadTemplates() {
|
||
document.getElementById('loading').style.display = 'block';
|
||
document.getElementById('templates-container').style.display = 'none';
|
||
|
||
try {
|
||
const response = await fetch('/templates');
|
||
const data = await response.json();
|
||
|
||
document.getElementById('template-count').textContent = data.count;
|
||
|
||
const templatesGrid = document.getElementById('templates-grid');
|
||
templatesGrid.innerHTML = '';
|
||
|
||
data.templates.forEach(template => {
|
||
const card = createTemplateCard(template);
|
||
templatesGrid.appendChild(card);
|
||
});
|
||
|
||
document.getElementById('loading').style.display = 'none';
|
||
document.getElementById('templates-container').style.display = 'block';
|
||
|
||
} catch (error) {
|
||
document.getElementById('loading').innerHTML = '❌ Fehler beim Laden der Templates: ' + error.message;
|
||
}
|
||
}
|
||
|
||
function createTemplateCard(template) {
|
||
const card = document.createElement('div');
|
||
card.className = 'template-card';
|
||
|
||
const sizeKB = Math.round(template.size / 1024);
|
||
const modifiedDate = new Date(template.modified).toLocaleDateString('de-DE');
|
||
|
||
card.innerHTML = `
|
||
<div class="template-name">📄 ${template.name}</div>
|
||
<div class="template-info">
|
||
📊 Größe: ${sizeKB} KB<br>
|
||
📅 Geändert: ${modifiedDate}<br>
|
||
🏷️ Tags: ${template.tags} (${template.simpleTags} einfach, ${template.tables} Tabellen)
|
||
</div>
|
||
<div class="action-buttons">
|
||
<button onclick="demoTemplate('${template.name}')" class="btn btn-demo">
|
||
🚀 Demo
|
||
</button>
|
||
<a href="${template.analyzeUrl}" target="_blank" class="btn btn-analyze">
|
||
📊 Analysieren
|
||
</a>
|
||
<button onclick="testTemplate('${template.name}')" class="btn btn-test">
|
||
🎲 Testen
|
||
</button>
|
||
<a href="/webdav/templates/${template.name}" class="btn btn-webdav">
|
||
📁 Download
|
||
</a>
|
||
<button onclick="openInWord('${template.name}')" class="btn btn-word">
|
||
📝 In Word öffnen
|
||
</button>
|
||
</div>
|
||
`;
|
||
|
||
return card;
|
||
}
|
||
|
||
async function demoTemplate(templateName) {
|
||
const rowCount = prompt('Anzahl Tabellenzeilen für Demo:', '3');
|
||
if (!rowCount) return;
|
||
|
||
try {
|
||
const response = await fetch(`/demo/${templateName}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({ tables: { mitarbeiter: parseInt(rowCount), positionen: parseInt(rowCount) } })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
const message = `🚀 Demo erfolgreich erstellt!
|
||
|
||
📄 Template: ${templateName}
|
||
<EFBFBD> Demo-Dokument erstellt: ${result.file}
|
||
🎉 ${result.message}
|
||
|
||
📊 Analyse:
|
||
• Einfache Tags: ${result.analysis.simpleTags.length}
|
||
• Tabellen: ${result.analysis.tables.length}
|
||
|
||
🔗 Aktionen:
|
||
• Herunterladen: ${window.location.origin}${result.download}
|
||
|
||
📋 Gefundene Tags: ${result.analysis.simpleTags.join(', ')}
|
||
<EFBFBD> Tabellen: ${result.analysis.tables.join(', ')}`;
|
||
|
||
alert(message);
|
||
|
||
// Optional: Demo-Dokument direkt herunterladen
|
||
if (confirm('Demo-Dokument jetzt herunterladen?')) {
|
||
window.location.href = result.download;
|
||
}
|
||
} else {
|
||
alert('❌ Fehler: ' + result.error);
|
||
}
|
||
|
||
} catch (error) {
|
||
alert('❌ Fehler beim Erstellen der Demo: ' + error.message);
|
||
}
|
||
}
|
||
|
||
async function testTemplate(templateName) {
|
||
const rowCount = prompt('Anzahl Tabellenzeilen für Test:', '3');
|
||
if (!rowCount) return;
|
||
|
||
try {
|
||
const response = await fetch(`/demo/${templateName}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({ tables: { mitarbeiter: parseInt(rowCount), positionen: parseInt(rowCount) } })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
const message = `✅ Test-Dokument erstellt!
|
||
|
||
📄 Datei: ${result.file}
|
||
<EFBFBD> ${result.message}
|
||
|
||
🔗 Aktionen:
|
||
• Herunterladen: ${window.location.origin}${result.download}
|
||
|
||
📊 Analyse: ${result.analysis.simpleTags.length} Tags, ${result.analysis.tables.length} Tabellen`;
|
||
|
||
alert(message);
|
||
|
||
// Optional: Test-Dokument direkt herunterladen
|
||
if (confirm('Test-Dokument jetzt herunterladen?')) {
|
||
window.location.href = result.download;
|
||
}
|
||
} else {
|
||
alert('❌ Fehler: ' + result.error);
|
||
}
|
||
|
||
} catch (error) {
|
||
alert('❌ Fehler beim Erstellen des Test-Dokuments: ' + error.message);
|
||
}
|
||
}
|
||
|
||
function openInWord(templateName) {
|
||
// WebDAV-URL für direktes Öffnen in Word
|
||
const webdavUrl = `${window.location.protocol}//${window.location.host}/webdav/templates/${templateName}`;
|
||
const msWordUrl = `ms-word:ofe|u|${webdavUrl}`;
|
||
|
||
// Versuche Word zu öffnen
|
||
try {
|
||
window.location.href = msWordUrl;
|
||
|
||
// Fallback-Information für den Benutzer
|
||
setTimeout(() => {
|
||
if (confirm(`Word konnte nicht automatisch geöffnet werden.\n\nMöchten Sie die Datei stattdessen herunterladen?\n\nWebDAV-URL: ${webdavUrl}`)) {
|
||
window.open(webdavUrl, '_blank');
|
||
}
|
||
}, 2000);
|
||
|
||
} catch (error) {
|
||
// Fallback: Datei herunterladen
|
||
window.open(webdavUrl, '_blank');
|
||
}
|
||
}
|
||
|
||
// Templates beim Laden der Seite laden
|
||
document.addEventListener('DOMContentLoaded', loadTemplates);
|
||
</script>
|
||
</body>
|
||
</html> |