diff --git a/include/class.pdf.php b/include/class.pdf.php index 9a7f0a7004eaf408f3fe08740596d31579699bde..32bc4b8810ecb66d5f9b4cbadea0a164ff7ed790 100644 --- a/include/class.pdf.php +++ b/include/class.pdf.php @@ -61,13 +61,18 @@ class Ticket2PDF extends mPDF } function _print() { - global $thisstaff, $cfg; + global $thisstaff, $thisclient, $cfg; if(!($ticket=$this->getTicket())) return; ob_start(); - include STAFFINC_DIR.'templates/ticket-print.tmpl.php'; + if ($thisstaff) + include STAFFINC_DIR.'templates/ticket-print.tmpl.php'; + elseif ($thisclient) + include CLIENTINC_DIR.'templates/ticket-print.tmpl.php'; + else + return; $html = ob_get_clean(); $this->WriteHtml($html, 0, true, true); diff --git a/include/class.ticket.php b/include/class.ticket.php index 5bdec7646de19b257870924cdfdcdf90b8bddb6f..7b95d9b82dc6c128db158958ce572fec58bde560 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -2177,7 +2177,7 @@ class Ticket { $pdf = new Ticket2PDF($this, $psize, $notes); $name='Ticket-'.$this->getNumber().'.pdf'; - $pdf->Output($name, 'I'); + Http::download($name, 'application/pdf', $pdf->Output($name, 'S')); //Remember what the user selected - for autoselect on the next print. $_SESSION['PAPER_SIZE'] = $psize; exit; diff --git a/include/client/templates/ticket-print.tmpl.php b/include/client/templates/ticket-print.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..d30973911165381db1097ca253461e021565ceb0 --- /dev/null +++ b/include/client/templates/ticket-print.tmpl.php @@ -0,0 +1,234 @@ +<html> + +<head> + <style type="text/css"> +@page { + header: html_def; + footer: html_def; + margin: 15mm; + margin-top: 30mm; + margin-bottom: 22mm; +} +.logo { + max-width: 220px; + max-height: 71px; + width: auto; + height: auto; + margin: 0; +} +#ticket_thread .message, +#ticket_thread .response, +#ticket_thread .note { + margin-top:10px; + border:1px solid #aaa; + border-bottom:2px solid #aaa; +} +#ticket_thread .header { + text-align:left; + border-bottom:1px solid #aaa; + padding:3px; + width: 100%; + table-layout: fixed; +} +#ticket_thread .message .header { + background:#C3D9FF; +} +#ticket_thread .response .header { + background:#DDD; +} +#ticket_thread .note .header { + background:#FFE; +} +#ticket_thread .info { + padding:5px; + background: snow; + border-top: 0.3mm solid #ccc; +} + +table.meta-data { + width: 100%; +} +table.custom-data { + margin-top: 10px; +} +table.custom-data th { + width: 25%; +} +table.custom-data th, +table.meta-data th { + text-align: right; + background-color: #ddd; + padding: 3px 8px; +} +table.meta-data td { + padding: 3px 8px; +} +.faded { + color:#666; +} +.pull-left { + float: left; +} +.pull-right { + float: right; +} +.flush-right { + text-align: right; +} +.flush-left { + text-align: left; +} +.ltr { + direction: ltr; + unicode-bidi: embed; +} +.headline { + border-bottom: 2px solid black; + font-weight: bold; +} +div.hr { + border-top: 0.2mm solid #bbb; + margin: 0.5mm 0; + font-size: 0.0001em; +} +.thread-entry, .thread-body { + page-break-inside: avoid; +} +<?php include ROOT_DIR . 'css/thread.css'; ?> + </style> +</head> +<body> + +<htmlpageheader name="def" style="display:none"> +<?php if ($logo = $cfg->getClientLogo()) { ?> + <img src="cid:<?php echo $logo->getKey(); ?>" class="logo"/> +<?php } else { ?> + <img src="<?php echo INCLUDE_DIR . 'fpdf/print-logo.png'; ?>" class="logo"/> +<?php } ?> + <div class="hr"> </div> + <table><tr> + <td class="flush-left"><?php echo (string) $ost->company; ?></td> + <td class="flush-right"><?php echo Format::db_daydatetime(Misc::gmtime()); ?></td> + </tr></table> +</htmlpageheader> + +<htmlpagefooter name="def" style="display:none"> + <div class="hr"> </div> + <table width="100%"><tr><td class="flush-left"> + Ticket #<?php echo $ticket->getNumber(); ?> printed by + <?php echo $thisclient->getName()->getFirst(); ?> on + <?php echo Format::db_daydatetime(Misc::gmtime()); ?> + </td> + <td class="flush-right"> + Page {PAGENO} + </td> + </tr></table> +</htmlpagefooter> + +<!-- Ticket metadata --> +<h1>Ticket #<?php echo $ticket->getNumber(); ?></h1> +<table class="meta-data" cellpadding="0" cellspacing="0"> +<tbody> +<tr> + <th><?php echo __('Status'); ?></th> + <td><?php echo $ticket->getStatus(); ?></td> + <th><?php echo __('Name'); ?></th> + <td><?php echo $ticket->getOwner()->getName(); ?></td> +</tr> +<tr> + <th><?php echo __('Priority'); ?></th> + <td><?php echo $ticket->getPriority(); ?></td> + <th><?php echo __('Email'); ?></th> + <td><?php echo $ticket->getEmail(); ?></td> +</tr> +<tr> + <th><?php echo __('Department'); ?></th> + <td><?php echo $ticket->getDept(); ?></td> + <th><?php echo __('Phone'); ?></th> + <td><?php echo $ticket->getPhoneNumber(); ?></td> +</tr> +<tr> + <th><?php echo __('Create Date'); ?></th> + <td><?php echo Format::db_datetime($ticket->getCreateDate()); ?></td> + <th><?php echo __('Source'); ?></th> + <td><?php echo $ticket->getSource(); ?></td> +</tr> +</tbody> +</table> + +<!-- Custom Data --> +<?php +foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) { + // Skip core fields shown earlier in the ticket view + // TODO: Rewrite getAnswers() so that one could write + // ->getAnswers()->filter(not(array('field__name__in'=> + // array('email', ...)))); + $answers = array_filter($form->getAnswers(), function ($a) { + return !in_array($a->getField()->get('name'), + array('email','subject','name','priority')) + && !$a->getField()->get('private'); + }); + if (count($answers) == 0) + continue; + ?> + <table class="custom-data" cellspacing="0" cellpadding="4" width="100%" border="0"> + <tr><td colspan="2" class="headline flush-left"><?php echo $form->getTitle(); ?></th></tr> + <?php foreach($answers as $a) { + if (!($v = $a->display())) continue; ?> + <tr> + <th><?php + echo $a->getField()->get('label'); + ?>:</th> + <td><?php + echo $v; + ?></td> + </tr> + <?php } ?> + </table> + <?php + $idx++; +} ?> + +<!-- Ticket Thread --> +<h2><?php echo $ticket->getSubject(); ?></h2> +<div id="ticket_thread"> +<?php +$types = array('M', 'R'); + +if ($thread = $ticket->getThreadEntries($types)) { + $threadTypes=array('M'=>'message','R'=>'response', 'N'=>'note'); + foreach ($thread as $entry) { ?> + <div class="thread-entry <?php echo $threadTypes[$entry['thread_type']]; ?>"> + <table class="header"><tr><td> + <span><?php + echo Format::db_datetime($entry['created']);?></span> + <span style="padding:0 1em" class="faded title"><?php + echo Format::truncate($entry['title'], 100); ?></span> + </td> + <td class="flush-right faded title" style="white-space:no-wrap"> + <?php + echo Format::htmlchars($entry['name'] ?: $entry['poster']); ?></span> + </td> + </tr></table> + <div class="thread-body"> + <div><?php echo $entry['body']->display('pdf'); ?></div> + </div> + <?php + if ($entry['attachments'] + && ($tentry = $ticket->getThreadEntry($entry['id'])) + && ($files = $tentry->getAttachments())) { ?> + <div class="info"> +<?php foreach ($files as $F) { ?> + <div> + <span><?php echo $F['name']; ?></span> + <span class="faded">(<?php echo Format::file_size($F['size']); ?>)</span> + </div> +<?php } ?> + </div> +<?php } ?> + </div> +<?php } +} ?> +</div> +</body> +</html> diff --git a/include/client/view.inc.php b/include/client/view.inc.php index 6fb76a9d969208436d36b1f072133a24fd368e9c..59ddf6b0bc75cdb4fa564a5a53c255fa4e13e5e5 100644 --- a/include/client/view.inc.php +++ b/include/client/view.inc.php @@ -33,12 +33,16 @@ if ($thisclient && $thisclient->isGuest() <h1> <?php echo sprintf(__('Ticket #%s'), $ticket->getNumber()); ?> <a href="tickets.php?id=<?php echo $ticket->getId(); ?>" title="<?php echo __('Reload'); ?>"><span class="Icon refresh"> </span></a> +<div class="pull-right"> + <a class="action-button" href="tickets.php?a=print&id=<?php + echo $ticket->getId(); ?>"><i class="icon-print"></i> <?php echo __('Print'); ?></a> <?php if ($ticket->hasClientEditableFields() // Only ticket owners can edit the ticket details (and other forms) && $thisclient->getId() == $ticket->getUserId()) { ?> <a class="action-button pull-right" href="tickets.php?a=edit&id=<?php echo $ticket->getId(); ?>"><i class="icon-edit"></i> <?php echo __('Edit'); ?></a> <?php } ?> +</div> </h1> </td> </tr> diff --git a/include/staff/templates/ticket-print.tmpl.php b/include/staff/templates/ticket-print.tmpl.php index bd9ed2aa74873535a86a439102c2b77188ac39c9..430c775d9cd2490d45c45870f60017ca479d5101 100644 --- a/include/staff/templates/ticket-print.tmpl.php +++ b/include/staff/templates/ticket-print.tmpl.php @@ -6,7 +6,8 @@ header: html_def; footer: html_def; margin: 15mm; - margin-top: 35mm; + margin-top: 30mm; + margin-bottom: 22mm; } .logo { max-width: 220px; @@ -26,7 +27,8 @@ text-align:left; border-bottom:1px solid #aaa; padding:3px; - position: relative; + width: 100%; + table-layout: fixed; } #ticket_thread .message .header { background:#C3D9FF; @@ -39,9 +41,8 @@ } #ticket_thread .info { padding:5px; - background:#F4FAFF; - height:16px; - line-height:16px; + background: snow; + border-top: 0.3mm solid #ccc; } table.meta-data { @@ -70,8 +71,6 @@ table.meta-data td { } .pull-right { float: right; - position: absolute; - right: 0; } .flush-right { text-align: right; @@ -92,6 +91,9 @@ div.hr { margin: 0.5mm 0; font-size: 0.0001em; } +.thread-entry, .thread-body { + page-break-inside: avoid; +} <?php include ROOT_DIR . 'css/thread.css'; ?> </style> </head> @@ -111,7 +113,7 @@ div.hr { </htmlpageheader> <htmlpagefooter name="def" style="display:none"> - <hr class="tight faded"/> + <div class="hr"> </div> <table width="100%"><tr><td class="flush-left"> Ticket #<?php echo $ticket->getNumber(); ?> printed by <?php echo $thisstaff->getUserName(); ?> on @@ -235,12 +237,18 @@ if ($thread = $ticket->getThreadEntries($types)) { <div class="thread-body"> <div><?php echo $entry['body']->display('pdf'); ?></div> <?php - if($entry['attachments'] + if ($entry['attachments'] && ($tentry = $ticket->getThreadEntry($entry['id'])) - && ($links = $tentry->getAttachmentsLinks())) {?> - <div class="info"><?php echo $tentry->getAttachmentsLinks(); ?></div> - <?php - } ?> + && ($files = $tentry->getAttachments())) { ?> + <div class="info"> +<?php foreach ($files as $F) { ?> + <div> + <span><?php echo $F['name']; ?></span> + <span class="faded">(<?php echo Format::file_size($F['size']); ?>)</span> + </div> +<?php } ?> + </div> +<?php } ?> </div> </div> <?php } diff --git a/tickets.php b/tickets.php index 2161b67b2658326dcc29a388286a96be077b7e59..052762488b814df35147478e39892fa07385cdb5 100644 --- a/tickets.php +++ b/tickets.php @@ -40,7 +40,7 @@ $messageField = $tform->getField('message'); $attachments = $messageField->getWidget()->getAttachments(); //Process post...depends on $ticket object above. -if($_POST && is_object($ticket) && $ticket->getId()): +if ($_POST && is_object($ticket) && $ticket->getId()) { $errors=array(); switch(strtolower($_POST['a'])){ case 'edit': @@ -101,7 +101,16 @@ if($_POST && is_object($ticket) && $ticket->getId()): $errors['err']=__('Unknown action'); } $ticket->reload(); -endif; +} +elseif (is_object($ticket) && $ticket->getId()) { + switch(strtolower($_REQUEST['a'])) { + case 'print': + if (!$ticket || !$ticket->pdfExport($_REQUEST['psize'])) + $errors['err'] = __('Internal error: Unable to export the ticket to PDF for print.'); + break; + } +} + $nav->setActiveNav('tickets'); if($ticket && $ticket->checkUserAccess($thisclient)) { if (isset($_REQUEST['a']) && $_REQUEST['a'] == 'edit'