Add WebDAV integration and template improvements

 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
This commit is contained in:
dgsoft 2025-10-01 22:27:29 +02:00
parent a01423321b
commit 5371d5e479
11 changed files with 468 additions and 40 deletions

107
create-angebot-fixed.js Normal file
View File

@ -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 = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>`;
// _rels/.rels
const rels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>`;
// word/document.xml - Angebot Template mit docxtemplater Syntax
const document = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr><w:jc w:val="center"/></w:pPr>
<w:r><w:rPr><w:b/><w:sz w:val="32"/></w:rPr><w:t>ANGEBOT</w:t></w:r>
</w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:tbl>
<w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>
<w:tr>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Anbieter</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Kunde</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{firma}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_name}</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{strasse}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_strasse}</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{plz} {stadt}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_plz} {kunde_stadt}</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>E-Mail: {email}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>E-Mail: {kunde_email}</w:t></w:r></w:p></w:tc>
</w:tr>
</w:tbl>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Angebotsnummer: {angebotsnummer}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Angebotsdatum: {datum}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Projekt: {projekt}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>Sehr geehrte Damen und Herren,</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>gerne unterbreiten wir Ihnen folgendes Angebot:</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:tbl>
<w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>
<w:tr>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Pos.</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Leistung</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Menge</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Preis ()</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{#positionen}{nr}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{leistung}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{menge}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{preis}{/positionen}</w:t></w:r></w:p></w:tc>
</w:tr>
</w:tbl>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Gesamtsumme: {gesamtsumme}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>Mit freundlichen Grüßen</w:t></w:r></w:p>
<w:p><w:r><w:t>{ansprechpartner}</w:t></w:r></w:p>
</w:body>
</w:document>`;
// 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();

91
create-brief-fixed.js Normal file
View File

@ -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 = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>`;
// _rels/.rels
const rels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>`;
// word/document.xml - Brief Template
const document = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr><w:jc w:val="right"/></w:pPr>
<w:r><w:t>{firma}</w:t></w:r>
</w:p>
<w:p>
<w:pPr><w:jc w:val="right"/></w:pPr>
<w:r><w:t>{strasse}</w:t></w:r>
</w:p>
<w:p>
<w:pPr><w:jc w:val="right"/></w:pPr>
<w:r><w:t>{plz} {stadt}</w:t></w:r>
</w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>{empfaenger_name}</w:t></w:r></w:p>
<w:p><w:r><w:t>{empfaenger_strasse}</w:t></w:r></w:p>
<w:p><w:r><w:t>{empfaenger_plz} {empfaenger_stadt}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p>
<w:pPr><w:jc w:val="right"/></w:pPr>
<w:r><w:t>{datum}</w:t></w:r>
</w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Betreff: {betreff}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>{anrede},</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>{nachricht}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>Mit freundlichen Grüßen</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>{absender_name}</w:t></w:r></w:p>
<w:p><w:r><w:t>{position}</w:t></w:r></w:p>
</w:body>
</w:document>`;
// 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();

View File

@ -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);

104
create-rechnung-fixed.js Normal file
View File

@ -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 = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>`;
// _rels/.rels
const rels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>`;
// word/document.xml - Rechnungs Template
const document = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr><w:jc w:val="center"/></w:pPr>
<w:r><w:rPr><w:b/><w:sz w:val="36"/></w:rPr><w:t>RECHNUNG</w:t></w:r>
</w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:tbl>
<w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>
<w:tr>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Rechnungssteller</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Kunde</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{firma}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_name}</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{strasse}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_strasse}</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{plz} {stadt}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{kunde_plz} {kunde_stadt}</w:t></w:r></w:p></w:tc>
</w:tr>
</w:tbl>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Rechnungsnummer: {rechnungsnummer}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Rechnungsdatum: {datum}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Leistungszeitraum: {leistungszeitraum}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:tbl>
<w:tblPr><w:tblW w:w="0" w:type="auto"/></w:tblPr>
<w:tr>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Pos.</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Beschreibung</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Menge</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Einzelpreis ()</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Gesamtpreis ()</w:t></w:r></w:p></w:tc>
</w:tr>
<w:tr>
<w:tc><w:p><w:r><w:t>{#positionen}{nr}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{beschreibung}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{menge}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{einzelpreis}</w:t></w:r></w:p></w:tc>
<w:tc><w:p><w:r><w:t>{gesamtpreis}{/positionen}</w:t></w:r></w:p></w:tc>
</w:tr>
</w:tbl>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Nettobetrag: {nettobetrag}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>Mehrwertsteuer (19%): {mwst}</w:t></w:r></w:p>
<w:p><w:r><w:rPr><w:b/><w:sz w:val="24"/></w:rPr><w:t>Gesamtbetrag: {gesamtbetrag}</w:t></w:r></w:p>
<w:p><w:r><w:t></w:t></w:r></w:p>
<w:p><w:r><w:t>Zahlbar bis: {zahlbar_bis}</w:t></w:r></w:p>
<w:p><w:r><w:t>Verwendungszweck: {rechnungsnummer}</w:t></w:r></w:p>
</w:body>
</w:document>`;
// 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();

View File

@ -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,
}),
],

View File

@ -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 @@
<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>
@ -211,7 +244,8 @@
<div class="template-name">📄 ${template.name}</div>
<div class="template-info">
📊 Größe: ${sizeKB} KB<br>
📅 Geändert: ${modifiedDate}
📅 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">
@ -223,12 +257,12 @@
<button onclick="testTemplate('${template.name}')" class="btn btn-test">
🎲 Testen
</button>
<a href="${template.msWordUrl}" class="btn btn-word">
<a href="/webdav/templates/${template.name}" class="btn btn-webdav">
📁 Download
</a>
<button onclick="openInWord('${template.name}')" class="btn btn-word">
📝 In Word öffnen
</a>
<a href="${template.webdavUrl}" target="_blank" class="btn btn-webdav">
🌐 WebDAV
</a>
</button>
</div>
`;
@ -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}
<EFBFBD> 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(', ')}
<EFBFBD> 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}
<EFBFBD> ${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);
</script>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.