✅ Migration completed: - server.js: Complete rewrite using docxtemplater + pizzip - server-old.js: Backup of original docx-templates implementation - package.json: Added docxtemplater and pizzip dependencies - Removed docx-templates dependency 🚀 New features: - True dynamic tables with {#array}{field}{/array} syntax - Unlimited table rows (no more fixed array indices) - New API endpoints: /analyze, /generate, /demo - Simplified template creation scripts 🎯 Template improvements: - Updated template syntax examples - Added dynamic-template.docx with loop syntax - Enhanced template analysis functionality 📊 Benefits: - Real dynamic table generation - Better template flexibility - Cleaner API design - Preserved SSL and WebDAV functionality
334 lines
11 KiB
HTML
334 lines
11 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;
|
||
}
|
||
.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="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}
|
||
</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="${template.msWordUrl}" class="btn btn-word">
|
||
📝 In Word öffnen
|
||
</a>
|
||
<a href="${template.webdavUrl}" target="_blank" class="btn btn-webdav">
|
||
🌐 WebDAV
|
||
</a>
|
||
</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-template/${templateName}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({ rowCount: parseInt(rowCount) })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
const message = `🚀 One-Click Demo erfolgreich erstellt!
|
||
|
||
📄 Template: ${result.templateInfo.name}
|
||
📊 Analyse-Ergebnis:
|
||
• Tags gefunden: ${result.tagAnalysis.totalTags}
|
||
• Einfache Tags: ${result.tagAnalysis.tagBreakdown.simple}
|
||
• Tabellen: ${result.tagAnalysis.tagBreakdown.tables}
|
||
|
||
📝 Demo-Dokument erstellt:
|
||
• Datei: ${result.demoDocument.filename}
|
||
• Tabellenzeilen: ${rowCount} pro Tabelle
|
||
|
||
🔗 Aktionen:
|
||
• Herunterladen: ${window.location.origin}${result.demoDocument.downloadUrl}
|
||
• In Word öffnen: ${result.demoDocument.msWordUrl}
|
||
• WebDAV: ${window.location.origin}${result.demoDocument.webdavUrl}
|
||
|
||
📋 Gefundene Tags: ${result.tagAnalysis.foundTags.join(', ')}`;
|
||
|
||
alert(message);
|
||
|
||
// Optional: Demo-Dokument direkt öffnen
|
||
if (confirm('Demo-Dokument jetzt in Word öffnen?')) {
|
||
window.location.href = result.demoDocument.msWordUrl;
|
||
}
|
||
} 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(`/test-template/${templateName}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({ rowCount: parseInt(rowCount) })
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
const message = `✅ Test-Dokument erstellt!
|
||
|
||
📄 Datei: ${result.templateName}
|
||
🏷️ Tags gefunden: ${result.foundTags.length}
|
||
📊 Tabellen: ${result.tableNames.length}
|
||
|
||
🔗 Aktionen:
|
||
• Herunterladen: ${window.location.origin}${result.downloadUrl}
|
||
• In Word öffnen: ${result.msWordUrl}
|
||
• WebDAV: ${window.location.origin}${result.webdavUrl}`;
|
||
|
||
alert(message);
|
||
|
||
// Optional: Test-Dokument direkt öffnen
|
||
if (confirm('Test-Dokument jetzt in Word öffnen?')) {
|
||
window.location.href = result.msWordUrl;
|
||
}
|
||
} else {
|
||
alert('❌ Fehler: ' + result.error);
|
||
}
|
||
|
||
} catch (error) {
|
||
alert('❌ Fehler beim Erstellen des Test-Dokuments: ' + error.message);
|
||
}
|
||
}
|
||
|
||
// Templates beim Laden der Seite laden
|
||
document.addEventListener('DOMContentLoaded', loadTemplates);
|
||
</script>
|
||
</body>
|
||
</html> |