DolEditor für Notiz + Notiz unter Bild + Hack-Font im PDF [deploy]
All checks were successful
Deploy bericht / deploy (push) Successful in 1s
All checks were successful
Deploy bericht / deploy (push) Successful in 1s
- bericht_card.php: Plain-Textarea durch DolEditor (CKEditor, dolibarr_notes-Toolbar) ersetzt, damit Notizen formatiert werden können. - editor.js: getNoteValue()/setNoteValue() Helper für transparentes CKEditor/Textarea-Handling an allen Zugriffsstellen. - lib/bericht.lib.php: * bericht_write_note_html() rendert CKEditor-HTML via TCPDF::writeHTMLCell * Composite-Branch: Notiz direkt unter dem Bild statt mit SetY(-20) unten * bericht_ensure_hack_font() registriert Hack-TTFs beim ersten PDF-Run * Alle helvetica-SetFont-Calls auf Hack umgestellt (Corporate-Font) - fonts/: Hack-Regular/Bold/Italic/BoldItalic.ttf (Eddys Corporate-Font) - bericht_batch.php: ebenfalls Hack-Font
This commit is contained in:
parent
9c7ef73061
commit
021ef1cbb2
8 changed files with 109 additions and 29 deletions
|
|
@ -60,14 +60,14 @@ if ($action === 'generate') {
|
||||||
|
|
||||||
// Inhaltsverzeichnis-Seite
|
// Inhaltsverzeichnis-Seite
|
||||||
$pdf->AddPage('P', 'A4');
|
$pdf->AddPage('P', 'A4');
|
||||||
$pdf->SetFont('helvetica', 'B', 18);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 18);
|
||||||
$pdf->Cell(0, 12, 'Bericht-Sammlung', 0, 1, 'C');
|
$pdf->Cell(0, 12, 'Bericht-Sammlung', 0, 1, 'C');
|
||||||
$pdf->SetFont('helvetica', '', 11);
|
$pdf->SetFont(bericht_ensure_hack_font(), '', 11);
|
||||||
$pdf->Cell(0, 8, 'Erstellt: '.dol_print_date(dol_now(), 'dayhour'), 0, 1, 'C');
|
$pdf->Cell(0, 8, 'Erstellt: '.dol_print_date(dol_now(), 'dayhour'), 0, 1, 'C');
|
||||||
$pdf->Ln(8);
|
$pdf->Ln(8);
|
||||||
$pdf->SetFont('helvetica', 'B', 13);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 13);
|
||||||
$pdf->Cell(0, 8, 'Enthaltene Berichte ('.count($ids).')', 0, 1, 'L');
|
$pdf->Cell(0, 8, 'Enthaltene Berichte ('.count($ids).')', 0, 1, 'L');
|
||||||
$pdf->SetFont('helvetica', '', 10);
|
$pdf->SetFont(bericht_ensure_hack_font(), '', 10);
|
||||||
|
|
||||||
$berichte = array();
|
$berichte = array();
|
||||||
foreach ($ids as $id) {
|
foreach ($ids as $id) {
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,10 @@ if (!$bericht) {
|
||||||
print '</div>';
|
print '</div>';
|
||||||
print '<div class="bericht-page-note">';
|
print '<div class="bericht-page-note">';
|
||||||
print '<label>'.$langs->trans("BerichtNoteHint").'</label>';
|
print '<label>'.$langs->trans("BerichtNoteHint").'</label>';
|
||||||
print '<textarea id="page-note" rows="2"></textarea>';
|
// DolEditor (CKEditor) — wird im PDF mit writeHTMLCell gerendert
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
|
||||||
|
$noteEditor = new DolEditor('page-note', '', '100%', 120, 'dolibarr_notes', 'In', false, true, true, 4, '100%');
|
||||||
|
$noteEditor->Create(0);
|
||||||
print '</div>';
|
print '</div>';
|
||||||
print '</main>';
|
print '</main>';
|
||||||
|
|
||||||
|
|
|
||||||
BIN
fonts/Hack-Bold.ttf
Normal file
BIN
fonts/Hack-Bold.ttf
Normal file
Binary file not shown.
BIN
fonts/Hack-BoldItalic.ttf
Normal file
BIN
fonts/Hack-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
fonts/Hack-Italic.ttf
Normal file
BIN
fonts/Hack-Italic.ttf
Normal file
Binary file not shown.
BIN
fonts/Hack-Regular.ttf
Normal file
BIN
fonts/Hack-Regular.ttf
Normal file
Binary file not shown.
29
js/editor.js
29
js/editor.js
|
|
@ -26,6 +26,29 @@
|
||||||
const cfg = window.BERICHT_CONFIG || {};
|
const cfg = window.BERICHT_CONFIG || {};
|
||||||
if (!cfg.berichtid) { console.warn('Bericht: keine Konfiguration'); return; }
|
if (!cfg.berichtid) { console.warn('Bericht: keine Konfiguration'); return; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liest den Notiz-Text aus — funktioniert mit CKEditor (DolEditor) UND plain textarea
|
||||||
|
*/
|
||||||
|
function getNoteValue() {
|
||||||
|
if (window.CKEDITOR && window.CKEDITOR.instances && window.CKEDITOR.instances['page-note']) {
|
||||||
|
return window.CKEDITOR.instances['page-note'].getData() || '';
|
||||||
|
}
|
||||||
|
const el = document.getElementById('page-note');
|
||||||
|
return el ? el.value : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den Notiz-Text.
|
||||||
|
*/
|
||||||
|
function setNoteValue(html) {
|
||||||
|
if (window.CKEDITOR && window.CKEDITOR.instances && window.CKEDITOR.instances['page-note']) {
|
||||||
|
window.CKEDITOR.instances['page-note'].setData(html || '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const el = document.getElementById('page-note');
|
||||||
|
if (el) el.value = html || '';
|
||||||
|
}
|
||||||
|
|
||||||
// PDF.js worker (lokal)
|
// PDF.js worker (lokal)
|
||||||
if (window.pdfjsLib) {
|
if (window.pdfjsLib) {
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc = '/bericht/js/lib/pdf.worker.min.js';
|
pdfjsLib.GlobalWorkerOptions.workerSrc = '/bericht/js/lib/pdf.worker.min.js';
|
||||||
|
|
@ -157,7 +180,7 @@
|
||||||
if (wrapL) wrapL.classList.remove('empty'); // wird gleich aus loadPageMeta überschrieben falls gespeichert
|
if (wrapL) wrapL.classList.remove('empty'); // wird gleich aus loadPageMeta überschrieben falls gespeichert
|
||||||
|
|
||||||
fabricCanvas.clear();
|
fabricCanvas.clear();
|
||||||
document.getElementById('page-note').value = '';
|
setNoteValue('');
|
||||||
|
|
||||||
await loadPageMeta(); // setzt currentPageRotation + ggf. loadedFabricJson
|
await loadPageMeta(); // setzt currentPageRotation + ggf. loadedFabricJson
|
||||||
|
|
||||||
|
|
@ -354,7 +377,7 @@
|
||||||
if (!r.ok) return;
|
if (!r.ok) return;
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
if (data.fabric_json) loadedFabricJson = data.fabric_json;
|
if (data.fabric_json) loadedFabricJson = data.fabric_json;
|
||||||
if (data.note) document.getElementById('page-note').value = data.note;
|
if (data.note) setNoteValue(data.note);
|
||||||
if (typeof data.rotation !== 'undefined' && data.rotation !== null) {
|
if (typeof data.rotation !== 'undefined' && data.rotation !== null) {
|
||||||
currentPageRotation = parseInt(data.rotation, 10) || 0;
|
currentPageRotation = parseInt(data.rotation, 10) || 0;
|
||||||
}
|
}
|
||||||
|
|
@ -745,7 +768,7 @@
|
||||||
fd.append('token', cfg.token);
|
fd.append('token', cfg.token);
|
||||||
fd.append('pageid', currentPageId);
|
fd.append('pageid', currentPageId);
|
||||||
fd.append('fabric_json', JSON.stringify(fabricCanvas.toJSON(['bgImage'])));
|
fd.append('fabric_json', JSON.stringify(fabricCanvas.toJSON(['bgImage'])));
|
||||||
fd.append('note', document.getElementById('page-note').value || '');
|
fd.append('note', getNoteValue() || '');
|
||||||
fd.append('rotation', currentPageRotation);
|
fd.append('rotation', currentPageRotation);
|
||||||
|
|
||||||
// Phase 6: Composite-PNG
|
// Phase 6: Composite-PNG
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ function bericht_burn_annotations($pdf, $fabric_json, $x, $y, $w, $h)
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'textbox':
|
case 'textbox':
|
||||||
$fontsize = max(6, ($obj['fontSize'] ?? 16) * $sx * 2.83);
|
$fontsize = max(6, ($obj['fontSize'] ?? 16) * $sx * 2.83);
|
||||||
$pdf->SetFont('helvetica', '', $fontsize);
|
$pdf->SetFont(bericht_ensure_hack_font(), '', $fontsize);
|
||||||
$pdf->SetTextColor($stroke[0], $stroke[1], $stroke[2]);
|
$pdf->SetTextColor($stroke[0], $stroke[1], $stroke[2]);
|
||||||
$pdf->Text($ox, $oy + $fontsize * 0.35, $obj['text'] ?? '');
|
$pdf->Text($ox, $oy + $fontsize * 0.35, $obj['text'] ?? '');
|
||||||
break;
|
break;
|
||||||
|
|
@ -305,10 +305,64 @@ function bericht_render_cover_for_preview($template_path, $bericht, $parent, $te
|
||||||
* @param string $fmt A4/A3/A5/Letter
|
* @param string $fmt A4/A3/A5/Letter
|
||||||
* @param bool $fpdi_loaded
|
* @param bool $fpdi_loaded
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Registriert den Hack-Font (Eddys Corporate-Font) in TCPDF und gibt den Font-Key zurück.
|
||||||
|
* Konvertiert die TTFs beim ersten Aufruf via TCPDF_FONTS::addTTFfont ins TCPDF-Font-Verzeichnis.
|
||||||
|
* Fallback auf 'helvetica' wenn etwas schiefgeht.
|
||||||
|
*
|
||||||
|
* @return string Font-Key für $pdf->SetFont()
|
||||||
|
*/
|
||||||
|
function bericht_ensure_hack_font()
|
||||||
|
{
|
||||||
|
static $cached = null;
|
||||||
|
if ($cached !== null) return $cached;
|
||||||
|
|
||||||
|
if (!class_exists('TCPDF_FONTS')) {
|
||||||
|
$cached = 'helvetica';
|
||||||
|
return $cached;
|
||||||
|
}
|
||||||
|
$dir = dirname(__DIR__).'/fonts';
|
||||||
|
$files = array(
|
||||||
|
'' => $dir.'/Hack-Regular.ttf',
|
||||||
|
'B' => $dir.'/Hack-Bold.ttf',
|
||||||
|
'I' => $dir.'/Hack-Italic.ttf',
|
||||||
|
'BI' => $dir.'/Hack-BoldItalic.ttf',
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
$key = null;
|
||||||
|
foreach ($files as $style => $path) {
|
||||||
|
if (!file_exists($path)) continue;
|
||||||
|
$k = TCPDF_FONTS::addTTFfont($path, 'TrueTypeUnicode', '', 32);
|
||||||
|
if ($style === '' && $k) $key = $k;
|
||||||
|
}
|
||||||
|
$cached = $key ?: 'helvetica';
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$cached = 'helvetica';
|
||||||
|
}
|
||||||
|
return $cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rendert eine HTML-Notiz (CKEditor-Output) mit TCPDF::writeHTMLCell
|
||||||
|
* in einen reservierten Bereich unterhalb des Bildes.
|
||||||
|
*/
|
||||||
|
function bericht_write_note_html($pdf, $html, $x, $y, $w, $h)
|
||||||
|
{
|
||||||
|
if (empty($html)) return;
|
||||||
|
// CKEditor liefert <p>…</p> — TCPDF kann das direkt
|
||||||
|
$pdf->SetFont(bericht_ensure_hack_font(), '', 9);
|
||||||
|
$pdf->SetTextColor(40, 40, 40);
|
||||||
|
// Border 0, kein Auto-Pagebreak damit die Notiz im reservierten Bereich bleibt
|
||||||
|
$autoPB = $pdf->getAutoPageBreak();
|
||||||
|
$bMargin = $pdf->getBreakMargin();
|
||||||
|
$pdf->SetAutoPageBreak(false, 0);
|
||||||
|
$pdf->writeHTMLCell($w, $h, $x, $y, $html, 0, 1, false, true, 'L', true);
|
||||||
|
$pdf->SetAutoPageBreak($autoPB, $bMargin);
|
||||||
|
}
|
||||||
|
|
||||||
function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
{
|
{
|
||||||
// Phase 6: Wenn der Editor ein Composite-PNG hochgeladen hat, nutzen wir das
|
// Phase 6: Wenn der Editor ein Composite-PNG hochgeladen hat, nutzen wir das direkt
|
||||||
// direkt — ein Bild über die ganze Seite. Keine Server-Shape-Logik nötig.
|
|
||||||
if (!empty($page->composite_path)) {
|
if (!empty($page->composite_path)) {
|
||||||
$full = bericht_resolve_data_path($page->composite_path);
|
$full = bericht_resolve_data_path($page->composite_path);
|
||||||
if ($full && file_exists($full)) {
|
if ($full && file_exists($full)) {
|
||||||
|
|
@ -316,8 +370,14 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
$pageW = $pdf->getPageWidth();
|
$pageW = $pdf->getPageWidth();
|
||||||
$pageH = $pdf->getPageHeight();
|
$pageH = $pdf->getPageHeight();
|
||||||
$margin = 10;
|
$margin = 10;
|
||||||
|
// Notiz-Bereich reservieren wenn eine Notiz existiert
|
||||||
|
$note_h = 0;
|
||||||
|
if (!empty($page->note)) {
|
||||||
|
// ca. 1/4 Seite für HTML-Notizen, aber mindestens 20mm, max 80mm
|
||||||
|
$note_h = max(20, min(80, $pageH * 0.25));
|
||||||
|
}
|
||||||
$maxW = $pageW - 2 * $margin;
|
$maxW = $pageW - 2 * $margin;
|
||||||
$maxH = $pageH - 2 * $margin - (empty($page->note) ? 0 : 10);
|
$maxH = $pageH - 2 * $margin - $note_h - ($note_h ? 4 : 0);
|
||||||
list($iw, $ih) = @getimagesize($full);
|
list($iw, $ih) = @getimagesize($full);
|
||||||
if ($iw && $ih) {
|
if ($iw && $ih) {
|
||||||
$ratio = min($maxW / $iw, $maxH / $ih);
|
$ratio = min($maxW / $iw, $maxH / $ih);
|
||||||
|
|
@ -327,9 +387,9 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
$pdf->Image($full, $x, $y, $w, $h);
|
$pdf->Image($full, $x, $y, $w, $h);
|
||||||
}
|
}
|
||||||
if (!empty($page->note)) {
|
if (!empty($page->note)) {
|
||||||
$pdf->SetY(-20);
|
// Notiz direkt unter dem Bild rendern — kein SetY(-20), keine auto-Page-Break
|
||||||
$pdf->SetFont('helvetica', 'I', 9);
|
$note_y = $margin + ($ih && $iw ? ($ih * min($maxW / $iw, $maxH / $ih)) : $maxH) + 4;
|
||||||
$pdf->MultiCell(0, 5, $page->note, 0, 'L');
|
bericht_write_note_html($pdf, $page->note, $margin, $note_y, $maxW, $note_h);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -342,13 +402,13 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
$pdf->AddPage($ori, $fmt);
|
$pdf->AddPage($ori, $fmt);
|
||||||
$pageW = $pdf->getPageWidth();
|
$pageW = $pdf->getPageWidth();
|
||||||
$pageH = $pdf->getPageHeight();
|
$pageH = $pdf->getPageHeight();
|
||||||
$pdf->SetFont('helvetica', 'B', 32);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 32);
|
||||||
$pdf->SetTextColor(40, 40, 40);
|
$pdf->SetTextColor(40, 40, 40);
|
||||||
$pdf->SetY($pageH / 2 - 20);
|
$pdf->SetY($pageH / 2 - 20);
|
||||||
$pdf->MultiCell(0, 20, $page->title, 0, 'C');
|
$pdf->MultiCell(0, 20, $page->title, 0, 'C');
|
||||||
if (!empty($page->note)) {
|
if (!empty($page->note)) {
|
||||||
$pdf->Ln(12);
|
$pdf->Ln(12);
|
||||||
$pdf->SetFont('helvetica', '', 12);
|
$pdf->SetFont(bericht_ensure_hack_font(), '', 12);
|
||||||
$pdf->MultiCell(0, 8, $page->note, 0, 'C');
|
$pdf->MultiCell(0, 8, $page->note, 0, 'C');
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -364,7 +424,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
$margin = 10;
|
$margin = 10;
|
||||||
$title_h = !empty($page->title) ? 12 : 0;
|
$title_h = !empty($page->title) ? 12 : 0;
|
||||||
if ($title_h) {
|
if ($title_h) {
|
||||||
$pdf->SetFont('helvetica', 'B', 16);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 16);
|
||||||
$pdf->SetY($margin);
|
$pdf->SetY($margin);
|
||||||
$pdf->MultiCell(0, $title_h, $page->title, 0, 'C');
|
$pdf->MultiCell(0, $title_h, $page->title, 0, 'C');
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +445,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
|
|
||||||
$x0 = $margin + $slot * ($w_each + $gap);
|
$x0 = $margin + $slot * ($w_each + $gap);
|
||||||
// Label
|
// Label
|
||||||
$pdf->SetFont('helvetica', 'B', 11);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 11);
|
||||||
$pdf->SetXY($x0, $top);
|
$pdf->SetXY($x0, $top);
|
||||||
$pdf->Cell($w_each, $label_h, $label, 0, 0, 'C');
|
$pdf->Cell($w_each, $label_h, $label, 0, 0, 'C');
|
||||||
// Bild darunter
|
// Bild darunter
|
||||||
|
|
@ -397,9 +457,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
}
|
}
|
||||||
bericht_burn_annotations($pdf, $page->fabric_json, 0, 0, $pageW, $pageH);
|
bericht_burn_annotations($pdf, $page->fabric_json, 0, 0, $pageW, $pageH);
|
||||||
if (!empty($page->note)) {
|
if (!empty($page->note)) {
|
||||||
$pdf->SetY(-20);
|
bericht_write_note_html($pdf, $page->note, 10, $pdf->getPageHeight() - 22, $pdf->getPageWidth() - 20, 18);
|
||||||
$pdf->SetFont('helvetica', 'I', 9);
|
|
||||||
$pdf->MultiCell(0, 5, $page->note, 0, 'L');
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +474,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
// Titel oben
|
// Titel oben
|
||||||
$title_h = 0;
|
$title_h = 0;
|
||||||
if (!empty($page->title)) {
|
if (!empty($page->title)) {
|
||||||
$pdf->SetFont('helvetica', 'B', 16);
|
$pdf->SetFont(bericht_ensure_hack_font(), 'B', 16);
|
||||||
$pdf->SetY(10);
|
$pdf->SetY(10);
|
||||||
$pdf->MultiCell(0, 10, $page->title, 0, 'C');
|
$pdf->MultiCell(0, 10, $page->title, 0, 'C');
|
||||||
$title_h = 14;
|
$title_h = 14;
|
||||||
|
|
@ -443,9 +501,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
|
|
||||||
// Notiz unten
|
// Notiz unten
|
||||||
if (!empty($page->note)) {
|
if (!empty($page->note)) {
|
||||||
$pdf->SetY(-20);
|
bericht_write_note_html($pdf, $page->note, 10, $pdf->getPageHeight() - 22, $pdf->getPageWidth() - 20, 18);
|
||||||
$pdf->SetFont('helvetica', 'I', 9);
|
|
||||||
$pdf->MultiCell(0, 5, $page->note, 0, 'L');
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -489,9 +545,7 @@ function bericht_render_page_to_pdf($pdf, $page, $ori, $fmt, $fpdi_loaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($page->note)) {
|
if (!empty($page->note)) {
|
||||||
$pdf->SetY(-20);
|
bericht_write_note_html($pdf, $page->note, 10, $pdf->getPageHeight() - 22, $pdf->getPageWidth() - 20, 18);
|
||||||
$pdf->SetFont('helvetica', 'I', 9);
|
|
||||||
$pdf->MultiCell(0, 5, $page->note, 0, 'L');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue