diff --git a/create-angebot-fixed.js b/create-angebot-fixed.js
new file mode 100644
index 0000000..97084ed
--- /dev/null
+++ b/create-angebot-fixed.js
@@ -0,0 +1,107 @@
+const fs = require('fs');
+const path = require('path');
+const AdmZip = require('adm-zip');
+
+function createAngebotTemplate() {
+ const zip = new AdmZip();
+
+ // [Content_Types].xml
+ const contentTypes = `
+
+
+
+
+`;
+
+ // _rels/.rels
+ const rels = `
+
+
+`;
+
+ // word/document.xml - Angebot Template mit docxtemplater Syntax
+ const document = `
+
+
+
+
+ ANGEBOT
+
+
+
+
+
+
+
+ Anbieter
+ Kunde
+
+
+ {firma}
+ {kunde_name}
+
+
+ {strasse}
+ {kunde_strasse}
+
+
+ {plz} {stadt}
+ {kunde_plz} {kunde_stadt}
+
+
+ E-Mail: {email}
+ E-Mail: {kunde_email}
+
+
+
+
+
+ Angebotsnummer: {angebotsnummer}
+ Angebotsdatum: {datum}
+ Projekt: {projekt}
+
+
+ Sehr geehrte Damen und Herren,
+
+ gerne unterbreiten wir Ihnen folgendes Angebot:
+
+
+
+
+
+ Pos.
+ Leistung
+ Menge
+ Preis (€)
+
+
+ {#positionen}{nr}
+ {leistung}
+ {menge}
+ {preis}{/positionen}
+
+
+
+
+ Gesamtsumme: {gesamtsumme}€
+
+
+ Mit freundlichen Grüßen
+ {ansprechpartner}
+
+
+`;
+
+ // Füge Dateien zum ZIP hinzu
+ zip.addFile('[Content_Types].xml', Buffer.from(contentTypes, 'utf8'));
+ zip.addFile('_rels/.rels', Buffer.from(rels, 'utf8'));
+ zip.addFile('word/document.xml', Buffer.from(document, 'utf8'));
+
+ // Speichere die Datei
+ const outputPath = path.join(__dirname, 'templates', 'angebot-template.docx');
+ zip.writeZip(outputPath);
+
+ console.log('✅ Angebot-Template mit docxtemplater-Syntax erstellt:', outputPath);
+}
+
+createAngebotTemplate();
\ No newline at end of file
diff --git a/create-brief-fixed.js b/create-brief-fixed.js
new file mode 100644
index 0000000..7871344
--- /dev/null
+++ b/create-brief-fixed.js
@@ -0,0 +1,91 @@
+const fs = require('fs');
+const path = require('path');
+const AdmZip = require('adm-zip');
+
+function createBriefTemplate() {
+ const zip = new AdmZip();
+
+ // [Content_Types].xml
+ const contentTypes = `
+
+
+
+
+`;
+
+ // _rels/.rels
+ const rels = `
+
+
+`;
+
+ // word/document.xml - Brief Template
+ const document = `
+
+
+
+
+ {firma}
+
+
+
+ {strasse}
+
+
+
+ {plz} {stadt}
+
+
+
+
+
+ {empfaenger_name}
+ {empfaenger_strasse}
+ {empfaenger_plz} {empfaenger_stadt}
+
+
+
+
+
+
+ {datum}
+
+
+
+
+ Betreff: {betreff}
+
+
+
+ {anrede},
+
+
+
+ {nachricht}
+
+
+
+ Mit freundlichen Grüßen
+
+
+
+
+ {absender_name}
+ {position}
+
+
+`;
+
+ // Füge Dateien zum ZIP hinzu
+ zip.addFile('[Content_Types].xml', Buffer.from(contentTypes, 'utf8'));
+ zip.addFile('_rels/.rels', Buffer.from(rels, 'utf8'));
+ zip.addFile('word/document.xml', Buffer.from(document, 'utf8'));
+
+ // Speichere die Datei
+ const outputPath = path.join(__dirname, 'templates', 'brief-template.docx');
+ zip.writeZip(outputPath);
+
+ console.log('✅ Brief-Template mit docxtemplater-Syntax erstellt:', outputPath);
+}
+
+createBriefTemplate();
\ No newline at end of file
diff --git a/create-new-table-template.js b/create-new-table-template.js
new file mode 100644
index 0000000..0c17639
--- /dev/null
+++ b/create-new-table-template.js
@@ -0,0 +1,67 @@
+const fs = require('fs');
+const path = require('path');
+const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell } = require('docx');
+
+async function createTableTemplate() {
+ const doc = new Document({
+ sections: [{
+ properties: {},
+ children: [
+ new Paragraph({
+ children: [
+ new TextRun({
+ text: "DYNAMISCHES TABELLEN-TEMPLATE",
+ bold: true,
+ size: 32,
+ }),
+ ],
+ }),
+ new Paragraph({ children: [new TextRun({ text: "" })] }),
+ new Paragraph({ children: [new TextRun({ text: "Projekt: {projekt}", bold: true })] }),
+ new Paragraph({ children: [new TextRun({ text: "Datum: {datum}" })] }),
+ new Paragraph({ children: [new TextRun({ text: "Ersteller: {ersteller}" })] }),
+ new Paragraph({ children: [new TextRun({ text: "" })] }),
+ new Paragraph({
+ children: [new TextRun({ text: "MITARBEITERLISTE:", bold: true, size: 24 })],
+ }),
+ new Table({
+ rows: [
+ new TableRow({
+ children: [
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "Nr.", bold: true })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "Name", bold: true })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "Position", bold: true })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "E-Mail", bold: true })] })] }),
+ ],
+ }),
+ new TableRow({
+ children: [
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "{#mitarbeiter}{nr}" })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "{name}" })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "{position}" })] })] }),
+ new TableCell({ children: [new Paragraph({ children: [new TextRun({ text: "{email}{/mitarbeiter}" })] })] }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({ children: [new TextRun({ text: "" })] }),
+ new Paragraph({
+ children: [
+ new TextRun({
+ text: "Status: {status}",
+ bold: true
+ })
+ ]
+ }),
+ ],
+ }],
+ });
+
+ const buffer = await Packer.toBuffer(doc);
+ const outputPath = path.join(__dirname, 'templates', 'tabellen-template.docx');
+ fs.writeFileSync(outputPath, buffer);
+
+ console.log('✅ Tabellen-Template mit docxtemplater Loop-Syntax erstellt');
+}
+
+createTableTemplate().catch(console.error);
\ No newline at end of file
diff --git a/create-rechnung-fixed.js b/create-rechnung-fixed.js
new file mode 100644
index 0000000..7f60d8f
--- /dev/null
+++ b/create-rechnung-fixed.js
@@ -0,0 +1,104 @@
+const fs = require('fs');
+const path = require('path');
+const AdmZip = require('adm-zip');
+
+function createRechnungTemplate() {
+ const zip = new AdmZip();
+
+ // [Content_Types].xml
+ const contentTypes = `
+
+
+
+
+`;
+
+ // _rels/.rels
+ const rels = `
+
+
+`;
+
+ // word/document.xml - Rechnungs Template
+ const document = `
+
+
+
+
+ RECHNUNG
+
+
+
+
+
+
+
+ Rechnungssteller
+ Kunde
+
+
+ {firma}
+ {kunde_name}
+
+
+ {strasse}
+ {kunde_strasse}
+
+
+ {plz} {stadt}
+ {kunde_plz} {kunde_stadt}
+
+
+
+
+
+ Rechnungsnummer: {rechnungsnummer}
+ Rechnungsdatum: {datum}
+ Leistungszeitraum: {leistungszeitraum}
+
+
+
+
+
+
+ Pos.
+ Beschreibung
+ Menge
+ Einzelpreis (€)
+ Gesamtpreis (€)
+
+
+ {#positionen}{nr}
+ {beschreibung}
+ {menge}
+ {einzelpreis}
+ {gesamtpreis}{/positionen}
+
+
+
+
+
+ Nettobetrag: {nettobetrag}€
+ Mehrwertsteuer (19%): {mwst}€
+ Gesamtbetrag: {gesamtbetrag}€
+
+
+ Zahlbar bis: {zahlbar_bis}
+ Verwendungszweck: {rechnungsnummer}
+
+
+`;
+
+ // Füge Dateien zum ZIP hinzu
+ zip.addFile('[Content_Types].xml', Buffer.from(contentTypes, 'utf8'));
+ zip.addFile('_rels/.rels', Buffer.from(rels, 'utf8'));
+ zip.addFile('word/document.xml', Buffer.from(document, 'utf8'));
+
+ // Speichere die Datei
+ const outputPath = path.join(__dirname, 'templates', 'rechnung-template.docx');
+ zip.writeZip(outputPath);
+
+ console.log('✅ Rechnungs-Template mit docxtemplater-Syntax erstellt:', outputPath);
+}
+
+createRechnungTemplate();
\ No newline at end of file
diff --git a/create-simple-template.js b/create-simple-template.js
index 041d111..7d0b293 100644
--- a/create-simple-template.js
+++ b/create-simple-template.js
@@ -20,21 +20,21 @@ async function createTestTemplate() {
new Paragraph({
children: [
new TextRun({
- text: "Kunde: ++name++",
+ text: "Kunde: {name}",
}),
],
}),
new Paragraph({
children: [
new TextRun({
- text: "E-Mail: ++email++",
+ text: "E-Mail: {email}",
}),
],
}),
new Paragraph({
children: [
new TextRun({
- text: "Datum: ++date++",
+ text: "Datum: {datum}",
}),
],
}),
@@ -56,7 +56,14 @@ async function createTestTemplate() {
new Paragraph({
children: [
new TextRun({
- text: "Artikel 1: ++items[0].product++ (++items[0].quantity++x) - ++items[0].price++€",
+ text: "Projekt: {projekt}",
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new TextRun({
+ text: "Status: {status}",
}),
],
}),
@@ -70,7 +77,7 @@ async function createTestTemplate() {
new Paragraph({
children: [
new TextRun({
- text: "Gesamtsumme: ++total++€",
+ text: "Gesamtsumme: {betrag}€",
bold: true,
}),
],
diff --git a/public/templates.html b/public/templates.html
index ef7075b..d7fcbcd 100644
--- a/public/templates.html
+++ b/public/templates.html
@@ -33,6 +33,23 @@
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;
}
@@ -150,6 +167,22 @@
+
+
🌐 WebDAV Template-Bearbeitung
+
Template direkt in Word bearbeiten:
+
+ - Klicken Sie auf "📝 In Word öffnen" bei einem Template
+ - Word öffnet das Template direkt vom Server
+ - Änderungen werden automatisch gespeichert
+
+
WebDAV-URLs:
+
+ - Templates:
${window.location.origin}/webdav/templates/
+ - Generierte Dateien:
${window.location.origin}/webdav/output/
+
+
💡 Tipp: Sie können diese URLs auch als Netzlaufwerk in Windows einbinden!
+
+
🚀 Neue Features:
@@ -211,7 +244,8 @@
📄 ${template.name}
📊 Größe: ${sizeKB} KB
- 📅 Geändert: ${modifiedDate}
+ 📅 Geändert: ${modifiedDate}
+ 🏷️ Tags: ${template.tags} (${template.simpleTags} einfach, ${template.tables} Tabellen)
`;
@@ -240,41 +274,38 @@
if (!rowCount) return;
try {
- const response = await fetch(`/demo-template/${templateName}`, {
+ const response = await fetch(`/demo/${templateName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
- body: JSON.stringify({ rowCount: parseInt(rowCount) })
+ body: JSON.stringify({ tables: { mitarbeiter: parseInt(rowCount), positionen: parseInt(rowCount) } })
});
const result = await response.json();
if (result.success) {
- const message = `🚀 One-Click Demo erfolgreich erstellt!
+ const message = `🚀 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}
+📄 Template: ${templateName}
+� Demo-Dokument erstellt: ${result.file}
+🎉 ${result.message}
-📝 Demo-Dokument erstellt:
- • Datei: ${result.demoDocument.filename}
- • Tabellenzeilen: ${rowCount} pro Tabelle
+📊 Analyse:
+ • Einfache Tags: ${result.analysis.simpleTags.length}
+ • Tabellen: ${result.analysis.tables.length}
🔗 Aktionen:
-• Herunterladen: ${window.location.origin}${result.demoDocument.downloadUrl}
-• In Word öffnen: ${result.demoDocument.msWordUrl}
-• WebDAV: ${window.location.origin}${result.demoDocument.webdavUrl}
+• Herunterladen: ${window.location.origin}${result.download}
-📋 Gefundene Tags: ${result.tagAnalysis.foundTags.join(', ')}`;
+📋 Gefundene Tags: ${result.analysis.simpleTags.join(', ')}
+� Tabellen: ${result.analysis.tables.join(', ')}`;
alert(message);
- // Optional: Demo-Dokument direkt öffnen
- if (confirm('Demo-Dokument jetzt in Word öffnen?')) {
- window.location.href = result.demoDocument.msWordUrl;
+ // Optional: Demo-Dokument direkt herunterladen
+ if (confirm('Demo-Dokument jetzt herunterladen?')) {
+ window.location.href = result.download;
}
} else {
alert('❌ Fehler: ' + result.error);
@@ -290,12 +321,12 @@
if (!rowCount) return;
try {
- const response = await fetch(`/test-template/${templateName}`, {
+ const response = await fetch(`/demo/${templateName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
- body: JSON.stringify({ rowCount: parseInt(rowCount) })
+ body: JSON.stringify({ tables: { mitarbeiter: parseInt(rowCount), positionen: parseInt(rowCount) } })
});
const result = await response.json();
@@ -303,20 +334,19 @@
if (result.success) {
const message = `✅ Test-Dokument erstellt!
-📄 Datei: ${result.templateName}
-🏷️ Tags gefunden: ${result.foundTags.length}
-📊 Tabellen: ${result.tableNames.length}
+📄 Datei: ${result.file}
+� ${result.message}
🔗 Aktionen:
-• Herunterladen: ${window.location.origin}${result.downloadUrl}
-• In Word öffnen: ${result.msWordUrl}
-• WebDAV: ${window.location.origin}${result.webdavUrl}`;
+• Herunterladen: ${window.location.origin}${result.download}
+
+📊 Analyse: ${result.analysis.simpleTags.length} Tags, ${result.analysis.tables.length} Tabellen`;
alert(message);
- // Optional: Test-Dokument direkt öffnen
- if (confirm('Test-Dokument jetzt in Word öffnen?')) {
- window.location.href = result.msWordUrl;
+ // Optional: Test-Dokument direkt herunterladen
+ if (confirm('Test-Dokument jetzt herunterladen?')) {
+ window.location.href = result.download;
}
} else {
alert('❌ Fehler: ' + result.error);
@@ -327,6 +357,28 @@
}
}
+ 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);
diff --git a/templates/angebot-template.docx b/templates/angebot-template.docx
index 17bfa3b..4bdfdc7 100644
Binary files a/templates/angebot-template.docx and b/templates/angebot-template.docx differ
diff --git a/templates/brief-template.docx b/templates/brief-template.docx
index 6018df0..c9e1ebf 100644
Binary files a/templates/brief-template.docx and b/templates/brief-template.docx differ
diff --git a/templates/rechnung-template.docx b/templates/rechnung-template.docx
index dd0cc04..e5975d0 100644
Binary files a/templates/rechnung-template.docx and b/templates/rechnung-template.docx differ
diff --git a/templates/simple-template.docx b/templates/simple-template.docx
index f9e2cbf..9213f7a 100644
Binary files a/templates/simple-template.docx and b/templates/simple-template.docx differ
diff --git a/templates/tabellen-template.docx b/templates/tabellen-template.docx
index 9911788..f777d1f 100644
Binary files a/templates/tabellen-template.docx and b/templates/tabellen-template.docx differ