diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index f228e300e742..61f7a45b5581 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -173,7 +173,11 @@ class PreviewController extends BaseController $html = new HtmlEngine(null, $invoice->invitations()->first(), 'invoice'); - $design = new Design(strtolower(request()->design['name'])); + if (isset(request()->design['name'])) { + $design = new Design(strtolower(request()->design['name'])); + } else { + $design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]); + } // $designer = new Designer($entity_obj, $design_object, $entity_obj->client->getSetting('pdf_variables'), lcfirst($entity)); // $html = $this->generateEntityHtml($designer, $entity_obj); @@ -193,7 +197,7 @@ class PreviewController extends BaseController ->design($design) ->build(); - info($maker->getCompiledHTML(true)); + // info($maker->getCompiledHTML(true)); $file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company()); diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index aa20b4c36133..56a9b1128621 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -45,6 +45,7 @@ class Design extends BaseDesign const MODERN = 'modern'; const PLAIN = 'plain'; const PLAYFUL = 'playful'; + const CUSTOM = 'custom'; public function __construct(string $design = null, array $options = []) { @@ -55,6 +56,12 @@ class Design extends BaseDesign public function html(): ?string { + if ($this->design == 'custom.html') { + return $this->composeFromPartials( + $this->options['custom_partials'] + ); + } + $path = isset($this->options['custom_path']) ? $this->options['custom_path'] : config('ninja.designs.base_path'); @@ -93,6 +100,10 @@ class Design extends BaseDesign 'id' => 'product-table', 'elements' => $this->productTable(), ], + 'product-table-footer' => [ + 'id' => 'product-table-footer', + 'elements' => $this->tableFooter(), + ], 'footer-elements' => [ 'id' => 'footer', 'elements' => [ @@ -166,7 +177,6 @@ class Design extends BaseDesign return [ ['element' => 'thead', 'elements' => $this->buildTableHeader()], ['element' => 'tbody', 'elements' => $this->buildTableBody()], - ['element' => 'tfoot', 'elements' => $this->tableFooter()], ]; } @@ -211,8 +221,8 @@ class Design extends BaseDesign $variables = $this->context['pdf_variables']['total_columns']; $elements = [ - ['element' => 'tr', 'elements' => [ - ['element' => 'td', 'content' => '$entity.public_notes', 'properties' => ['colspan' => '100%']], + ['element' => 'div', 'elements' => [ + ['element' => 'span', 'content' => '$entity.public_notes', 'properties' => ['data-element' => 'product-table-public-notes-label']], ]], ]; @@ -221,10 +231,10 @@ class Design extends BaseDesign continue; } - $elements[] = ['element' => 'tr', 'elements' => [ - ['element' => 'td', 'properties' => ['colspan' => $this->calculateColspan(2)]], - ['element' => 'td', 'content' => $variable.'_label'], - ['element' => 'td', 'content' => $variable], + $elements[] = ['element' => 'div', 'elements' => [ + ['element' => 'span', 'content' => 'This is placeholder for the 3rd fraction of element.', 'properties' => ['style' => 'opacity: 0%']], // Placeholder for fraction of element (3fr) + ['element' => 'span', 'content' => $variable.'_label'], + ['element' => 'span', 'content' => $variable], ]]; } diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index d05b9812c21e..4b682059b878 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -159,7 +159,7 @@ trait DesignHelpers public function sharedFooterElements() { - return ['element' => 'div', 'properties' => ['style' => 'display: flex; justify-content: space-between'], 'elements' => [ + return ['element' => 'div', 'properties' => ['style' => 'display: flex; justify-content: space-between; margin-top: 1.5rem'], 'elements' => [ ['element' => 'img', 'properties' => ['src' => '$contact.signature', 'style' => 'height: 5rem;']], ['element' => 'img', 'properties' => ['src' => '$app_url/images/created-by-invoiceninja-new.png', 'style' => 'height: 5rem;', 'hidden' => $this->entity->user->account->isPaid() ? 'true' : 'false']], ]]; @@ -186,4 +186,15 @@ trait DesignHelpers return false; } + + public function composeFromPartials(array $partials) + { + $html = ''; + + $html .= $partials['header']; + $html .= $partials['body']; + $html .= $partials['footer']; + + return $html; + } } diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index 5b1bb9f88ac0..6f05f2cbbcd1 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -55,7 +55,7 @@ trait PdfMakerUtilities if (isset($element['tag'])) { $node = $this->document->getElementsByTagName($element['tag'])->item(0); - } elseif (! is_null($this->document->getElementById($element['id']))) { + } elseif (!is_null($this->document->getElementById($element['id']))) { $node = $this->document->getElementById($element['id']); } else { continue; @@ -80,7 +80,7 @@ trait PdfMakerUtilities $processed = []; foreach ($children as $child) { - if (! isset($child['order'])) { + if (!isset($child['order'])) { $child['order'] = 0; } @@ -163,7 +163,11 @@ trait PdfMakerUtilities public function processOptions() { - if (! isset($this->options['all_pages_header']) && ! isset($this->options['all_pages_footer'])) { + if (!isset($this->options['all_pages_header']) || $this->options['all_pages_header'] == false) { + return; + } + + if (!isset($this->options['all_pages_footer']) || $this->options['all_pages_footer'] == false) { return; } @@ -265,6 +269,8 @@ trait PdfMakerUtilities $this->document->getElementById('repeat-content')->appendChild($clone); } + info($this->data['options']); + if ( $header = $this->document->getElementById('header') && isset($this->data['options']['all_pages_header']) && diff --git a/resources/views/pdf-designs/bold.html b/resources/views/pdf-designs/bold.html index 1cf41f0eb7ca..3e48b0e257bc 100644 --- a/resources/views/pdf-designs/bold.html +++ b/resources/views/pdf-designs/bold.html @@ -12,6 +12,11 @@ font-size: 14px; } + @page { + margin-top: 1cm; + margin-bottom: 1cm; + } + body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -89,31 +94,48 @@ padding: 2rem; font-size: 1.5rem; } + #product-table > thead > tr > th:last-child { + text-align: right; + } #product-table > tbody > tr > td { padding: 1.5rem; } + #product-table > tbody > tr > td:last-child { + text-align: right; + } #product-table > tbody > tr > td:first-child { font-weight: bold; } #product-table > tbody > tr:nth-child(odd) { background-color: #ebebeb; } - #product-table > tfoot > tr > td { - padding: 1.5rem; + + #product-table-footer > * { + display: grid; + grid-template-columns: 3fr 1fr 1fr; + padding-top: 1.2rem; + padding-left: 1.2rem; + gap: 20px; } - #product-table > tfoot [data-element='balance-due-label'], - #product-table > tfoot [data-element='balance-due'] { + #product-table-footer + > * + [data-element='product-table-balance-due-label'], + #product-table-footer > * [data-element='product-table-balance-due'] { font-weight: bold; font-size: 1.4rem; } - #product-table > tfoot [data-element='balance-due'] { + #product-table-footer > * [data-element='product-table-balance-due'] { color: #35a39a; } + #product-table-footer > * > :last-child { + text-align: right; + padding-right: 1.5rem; + }