diff --git a/include/class.pdf.php b/include/class.pdf.php index 20006d01ec6788b1ad9318a12166212882420b6b..7f149f342740716be8ef1d99951377f8d067073c 100644 --- a/include/class.pdf.php +++ b/include/class.pdf.php @@ -89,4 +89,35 @@ class Ticket2PDF extends mPDFWithLocalImages $this->WriteHtml($html, 0, true, true); } } + + +// Task print +class Task2PDF extends mPDFWithLocalImages { + + var $options = array(); + var $task = null; + + function __construct($task, $options=array()) { + + $this->task = $task; + $this->options = $options; + + parent::__construct('', $this->options['psize']); + $this->_print(); + } + + function _print() { + global $thisstaff, $cfg; + + if (!($task=$this->task) || !$thisstaff) + return; + + ob_start(); + include STAFFINC_DIR.'templates/task-print.tmpl.php'; + $html = ob_get_clean(); + $this->WriteHtml($html, 0, true, true); + + } +} + ?> diff --git a/include/class.task.php b/include/class.task.php index 6365d6c57a0cb450ccc668f875445164991ba89b..5f35fd5420d92575dcfa2b6afcc8a8718e79632e 100644 --- a/include/class.task.php +++ b/include/class.task.php @@ -155,6 +155,11 @@ class TaskModel extends VerySimpleModel { return $this->duedate; } + function getCloseDate() { + // TODO: have true close date + return $this->isClosed() ? $this->updated : ''; + } + function isOpen() { return $this->hasFlag(self::ISOPEN); } @@ -276,6 +281,14 @@ class Task extends TaskModel implements Threadable { return $assignees ? implode($glue, $assignees):''; } + function getParticipants() { + $participants = array(); + foreach ($this->getThread()->collaborators as $c) + $participants[] = $c->getName(); + + return $participants ? implode(', ', $participants) : ' '; + } + function getThreadId() { return $this->thread->getId(); } @@ -562,6 +575,27 @@ class Task extends TaskModel implements Threadable { return $note; } + function pdfExport($options=array()) { + global $thisstaff; + + require_once(INCLUDE_DIR.'class.pdf.php'); + if (!isset($options['psize'])) { + if ($_SESSION['PAPER_SIZE']) + $psize = $_SESSION['PAPER_SIZE']; + elseif (!$thisstaff || !($psize = $thisstaff->getDefaultPaperSize())) + $psize = 'Letter'; + + $options['psize'] = $psize; + } + + $pdf = new Task2PDF($this, $options); + $name = 'Task-'.$this->getNumber().'.pdf'; + Http::download($name, 'application/pdf', $pdf->Output($name, 'S')); + //Remember what the user selected - for autoselect on the next print. + $_SESSION['PAPER_SIZE'] = $options['psize']; + exit; + } + static function lookupIdByNumber($number) { $sql = 'SELECT id FROM '.TASK_TABLE .' WHERE `number`='.db_input($number); diff --git a/include/staff/templates/task-print.tmpl.php b/include/staff/templates/task-print.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..e07bef43711faa1bb56861a97b0124daf614cd08 --- /dev/null +++ b/include/staff/templates/task-print.tmpl.php @@ -0,0 +1,245 @@ +<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; +} +#task_thread .message, +#task_thread .response, +#task_thread .note { + margin-top:10px; + border:1px solid #aaa; + border-bottom:2px solid #aaa; +} +#task_thread .header { + text-align:left; + border-bottom:1px solid #aaa; + padding:3px; + width: 100%; + table-layout: fixed; +} +#task_thread .message .header { + background:#C3D9FF; +} +#task_thread .response .header { + background:#FFE0B3; +} +#task_thread .note .header { + background:#FFE; +} +#task_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::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"> + Task #<?php echo $task->getNumber(); ?> printed by + <?php echo $thisstaff->getUserName(); ?> on + <?php echo Format::daydatetime(Misc::gmtime()); ?> + </td> + <td class="flush-right"> + Page {PAGENO} + </td> + </tr></table> +</htmlpagefooter> + +<!-- Task metadata --> +<h1>Task #<?php echo $task->getNumber(); ?></h1> +<table class="meta-data" cellpadding="0" cellspacing="0"> +<tbody> +<tr> + <th><?php echo __('Status'); ?></th> + <td><?php echo $task->getStatus(); ?></td> + <th><?php echo __('Department'); ?></th> + <td><?php echo $task->getDept(); ?></td> +</tr> +<tr> + <th><?php echo __('Create Date'); ?></th> + <td><?php echo Format::datetime($task->getCreateDate()); ?></td> + <?php + if ($task->isOpen()) { ?> + <th><?php echo __('Assigned To'); ?></th> + <td><?php echo $task->getAssigned(); ?></td> + <?php + } else { ?> + <th><?php echo __('Closed By');?>:</th> + <td> + <?php + if (($staff = $task->getStaff())) + echo Format::htmlchars($staff->getName()); + else + echo '<span class="faded">— '.__('Unknown').' —</span>'; + ?> + </td> + <?php + } ?> +</tr> +<tr> + <?php + if ($task->isOpen()) {?> + <th><?php echo __('Due Date'); ?></th> + <td><?php echo Format::datetime($task->getDueDate()); ?></td> + <?php + } else { ?> + <th><?php echo __('Close Date'); ?></th> + <td><?php echo Format::datetime($task->getCloseDate()); ?></td> + <?php + } ?> + <th><?php echo __('Collaborators'); ?></th> + <td><?php echo $task->getParticipants(); ?></td> +</tr> +</tbody> +</table> +<!-- Custom Data --> +<?php +foreach (DynamicFormEntry::forObject($task->getId(), + ObjectModel::OBJECT_TYPE_TASK) as $form) { + // Skip core fields shown earlier on the view + $answers = $form->getAnswers()->exclude(Q::any(array( + 'field__flags__hasbit' => DynamicFormField::FLAG_EXT_STORED, + 'field__name__in' => array('title') + ))); + 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++; +} ?> + +<!-- Task Thread --> +<h2><?php echo $task->getTitle(); ?></h2> +<div id="task_thread"> +<?php +$types = array('M', 'R', 'N'); +if ($entries = $task->getThreadEntries($types)) { + $entryTypes=array('M'=>'message','R'=>'response', 'N'=>'note'); + foreach ($entries as $entry) { ?> + <div class="thread-entry <?php echo $entryTypes[$entry->type]; ?>"> + <table class="header" style="width:100%"><tr><td> + <span><?php + echo Format::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->getName()); ?></span> + </td> + </tr></table> + <div class="thread-body"> + <div><?php echo $entry->getBody()->display('pdf'); ?></div> + <?php + if ($entry->has_attachments + && ($files = $entry->attachments)) { ?> + <div class="info"> +<?php foreach ($files as $A) { ?> + <div> + <span><?php echo Format::htmlchars($A->file->name); ?></span> + <span class="faded">(<?php echo Format::file_size($A->file->size); ?>)</span> + </div> +<?php } ?> + </div> +<?php } ?> + </div> + </div> +<?php } +} ?> +</div> +</body> +</html> diff --git a/include/staff/templates/task-view.tmpl.php b/include/staff/templates/task-view.tmpl.php index 0e3f509268b1b5dcded6377b5a137af6be80a029..d3260b444283eb398218bb7bc02ba2e5a5a78ce0 100644 --- a/include/staff/templates/task-view.tmpl.php +++ b/include/staff/templates/task-view.tmpl.php @@ -174,8 +174,7 @@ if (!$ticket) { ?> }else { ?> <tr> <th><?php echo __('Close Date');?>:</th> - <td><?php echo 0 ? - Format::datetime($task->getCloseDate()) : ''; ?></td> + <td><?php echo Format::datetime($task->getCloseDate()); ?></td> </tr> <?php } @@ -208,7 +207,7 @@ if (!$ticket) { ?> <th width="100"><?php echo __('Closed By');?>:</th> <td> <?php - if (0 && ($staff = $task->getStaff())) + if (($staff = $task->getStaff())) echo Format::htmlchars($staff->getName()); else echo '<span class="faded">— '.__('Unknown').' —</span>';