Add possibility to print contact information (of a single contact)

pull/257/head
Aleksander Machniak 9 years ago
parent ae73c26f29
commit f7af22c780

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Add possibility to print contact information (of a single contact)
- Fix refreshing of drafts list when sending a message which was saved in meantime (#1490238)
RELEASE 1.1.0

@ -326,10 +326,7 @@ function rcube_webmail()
this.enable_command('download', 'print', true);
// show printing dialog
else if (this.env.action == 'print' && this.env.uid) {
if (bw.safari)
setTimeout('window.print()', 10);
else
window.print();
this.print_dialog();
}
// get unread count for each mailbox
@ -440,6 +437,9 @@ function rcube_webmail()
if (this.env.action == 'add' || this.env.action == 'edit' || this.env.action == 'search')
this.init_contact_form();
}
else if (this.env.action == 'print') {
this.print_dialog();
}
break;
@ -1176,7 +1176,15 @@ function rcube_webmail()
break;
case 'print':
if (this.env.action == 'get') {
if (this.task == 'addressbook') {
if (uid = this.contact_list.get_single_selection()) {
url = '&_action=print&_cid=' + uid;
if (this.env.source)
url += '&_source=' + urlencode(this.env.source);
this.open_window(this.env.comm_path + url, true, true);
}
}
else if (this.env.action == 'get') {
this.gui_objects.messagepartframe.contentWindow.print();
}
else if (uid = this.get_single_uid()) {
@ -4721,6 +4729,7 @@ function rcube_webmail()
clearTimeout(this.preview_timer);
var n, id, sid, contact, writable = false,
selected = list.selection.length,
source = this.env.source ? this.env.address_sources[this.env.source] : null;
// we don't have dblclick handler here, so use 200 instead of this.dblclick_time
@ -4729,7 +4738,7 @@ function rcube_webmail()
else if (this.env.contentframe)
this.show_contentframe(false);
if (list.selection.length) {
if (selected) {
list.draggable = false;
// no source = search result, we'll need to detect if any of
@ -4764,11 +4773,12 @@ function rcube_webmail()
// if a group is currently selected, and there is at least one contact selected
// thend we can enable the group-remove-selected command
this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0 && writable);
this.enable_command('compose', this.env.group || list.selection.length > 0);
this.enable_command('export-selected', 'copy', list.selection.length > 0);
this.enable_command('group-remove-selected', this.env.group && selected && writable);
this.enable_command('compose', this.env.group || selected);
this.enable_command('print', selected == 1);
this.enable_command('export-selected', 'copy', selected > 0);
this.enable_command('edit', id && writable);
this.enable_command('delete', 'move', list.selection.length > 0 && writable);
this.enable_command('delete', 'move', selected && writable);
return false;
};
@ -4881,8 +4891,8 @@ function rcube_webmail()
this.contact_list.data = {};
this.contact_list.clear(true);
this.show_contentframe(false);
this.enable_command('delete', 'move', 'copy', false);
this.enable_command('compose', this.env.group ? true : false);
this.enable_command('delete', 'move', 'copy', 'print', false);
this.enable_command('compose', this.env.group);
};
this.set_group_prop = function(prop)
@ -4922,7 +4932,7 @@ function rcube_webmail()
this.contact_list.clear_selection();
this.enable_command('compose', rec && rec.email);
this.enable_command('export-selected', rec && rec._type != 'group');
this.enable_command('export-selected', 'print', rec && rec._type != 'group');
}
else if (framed)
return false;
@ -7365,7 +7375,7 @@ function rcube_webmail()
this.enable_command('compose', (uid && this.contact_list.rows[uid]));
this.enable_command('delete', 'edit', writable);
this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
this.enable_command('export-selected', false);
this.enable_command('export-selected', 'print', false);
}
case 'move':
@ -8198,6 +8208,14 @@ function rcube_webmail()
return false;
}
};
this.print_dialog = function()
{
if (bw.safari)
setTimeout('window.print()', 10);
else
window.print();
};
} // end object rcube_webmail

@ -343,6 +343,7 @@ $labels['searchresult'] = 'Search result';
$labels['advsearch'] = 'Advanced Search';
$labels['advanced'] = 'Advanced';
$labels['other'] = 'Other';
$labels['printcontact'] = 'Print contact';
$labels['typehome'] = 'Home';
$labels['typework'] = 'Work';

@ -518,12 +518,13 @@ function rcmail_contact_form($form, $record, $attrib = null)
$plugin = $RCMAIL->plugins->exec_hook('contact_form', array(
'form' => $form, 'record' => $record));
$form = $plugin['form'];
$record = $plugin['record'];
$edit_mode = $RCMAIL->action != 'show';
$form = $plugin['form'];
$record = $plugin['record'];
$edit_mode = $RCMAIL->action != 'show' && $RCMAIL->action != 'print';
$del_button = $attrib['deleteicon'] ? html::img(array('src' => $RCMAIL->output->get_skin_file($attrib['deleteicon']), 'alt' => $RCMAIL->gettext('delete'))) : $RCMAIL->gettext('delete');
$out = '';
unset($attrib['deleteicon']);
$out = '';
// get default coltypes
$coltypes = $GLOBALS['CONTACT_COLTYPES'];
@ -544,8 +545,9 @@ function rcmail_contact_form($form, $record, $attrib = null)
foreach ($form as $section => $fieldset) {
// skip empty sections
if (empty($fieldset['content']))
if (empty($fieldset['content'])) {
continue;
}
$select_add = new html_select(array('class' => 'addfieldmenu', 'rel' => $section));
$select_add->add($RCMAIL->gettext('addfield'), '');
@ -555,18 +557,20 @@ function rcmail_contact_form($form, $record, $attrib = null)
$content = '';
// unset display name if it is composed from name parts
if ($record['name'] == rcube_addressbook::compose_display_name(array('name' => '') + (array)$record))
unset($record['name']);
if ($record['name'] == rcube_addressbook::compose_display_name(array('name' => '') + (array)$record)) {
unset($record['name']);
}
// group fields
$field_blocks = array(
'names' => array('prefix','firstname','middlename','surname','suffix'),
'displayname' => array('name'),
'nickname' => array('nickname'),
'names' => array('prefix','firstname','middlename','surname','suffix'),
'displayname' => array('name'),
'nickname' => array('nickname'),
'organization' => array('organization'),
'department' => array('department'),
'jobtitle' => array('jobtitle'),
'department' => array('department'),
'jobtitle' => array('jobtitle'),
);
foreach ($field_blocks as $blockname => $colnames) {
$fields = '';
foreach ($colnames as $col) {
@ -574,11 +578,16 @@ function rcmail_contact_form($form, $record, $attrib = null)
if (!$coltypes[$col])
continue;
// skip cols not listed in the form definition
if (is_array($fieldset['content']) && !in_array($col, array_keys($fieldset['content']))) {
continue;
}
// only string values are expected here
if (is_array($record[$col]))
$record[$col] = join(' ', $record[$col]);
if ($RCMAIL->action == 'show') {
if (!$edit_mode) {
if (!empty($record[$col]))
$fields .= html::span('namefield ' . $col, rcube::Q($record[$col])) . " ";
}
@ -611,11 +620,15 @@ function rcmail_contact_form($form, $record, $attrib = null)
$fullkey = $col.':'.$subtype;
// skip cols unknown to the backend
if (!$coltypes[$field])
if (!$coltypes[$field] && empty($colprop['value'])) {
continue;
}
// merge colprop with global coltype configuration
$colprop += $coltypes[$field];
if ($coltypes[$field]) {
$colprop += $coltypes[$field];
}
$label = isset($colprop['label']) ? $colprop['label'] : $RCMAIL->gettext($col);
// prepare subtype selector in edit mode
@ -624,8 +637,9 @@ function rcmail_contact_form($form, $record, $attrib = null)
$select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $colprop['label'] . ' ' . $RCMAIL->gettext('type')));
$select_subtype->add($subtype_names, $colprop['subtypes']);
}
else
else {
$select_subtype = null;
}
if (!empty($colprop['value'])) {
$values = (array)$colprop['value'];
@ -729,12 +743,21 @@ function rcmail_contact_form($form, $record, $attrib = null)
// display row with label
if ($label) {
if ($RCMAIL->action == 'print') {
$_label = rcube::Q($colprop['label'] . ($label != $colprop['label'] ? ' (' . $label . ')' : ''));
}
else {
$_label = $select_subtype ? $select_subtype->show($subtype) : html::label($colprop['id'], rcube::Q($label));
}
$rows .= html::div('row',
html::div('contactfieldlabel label', $select_subtype ? $select_subtype->show($subtype) : html::label($colprop['id'], rcube::Q($label))) .
html::div('contactfieldlabel label', $_label) .
html::div('contactfieldcontent '.$colprop['type'], $val));
}
else // row without label
// row without label
else {
$rows .= html::div('row', html::div('contactfield', $val));
}
}
// add option to the add-field menu
@ -745,9 +768,13 @@ function rcmail_contact_form($form, $record, $attrib = null)
// wrap rows in fieldgroup container
if ($rows) {
$content .= html::tag('fieldset', array('class' => 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col, 'style' => ($rows ? null : 'display:none')),
($colprop['subtypes'] ? html::tag('legend', null, rcube::Q($colprop['label'])) : ' ') .
$rows);
$c_class = 'contactfieldgroup ' . ($colprop['subtypes'] ? 'contactfieldgroupmulti ' : '') . 'contactcontroller' . $col;
$with_label = $colprop['subtypes'] && $RCMAIL->action != 'print';
$content .= html::tag(
'fieldset',
array('class' => $c_class, 'style' => ($rows ? null : 'display:none')),
($with_label ? html::tag('legend', null, rcube::Q($colprop['label'])) : ' ') . $rows
);
}
}
@ -769,9 +796,9 @@ function rcmail_contact_form($form, $record, $attrib = null)
}
if ($edit_mode) {
$RCMAIL->output->set_env('coltypes', $coltypes + $coltype_labels);
$RCMAIL->output->set_env('delbutton', $del_button);
$RCMAIL->output->add_label('delete');
$RCMAIL->output->set_env('coltypes', $coltypes + $coltype_labels);
$RCMAIL->output->set_env('delbutton', $del_button);
$RCMAIL->output->add_label('delete');
}
return $out;

@ -0,0 +1,138 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/addressbook/print.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2015, The Roundcube Dev Team |
| Copyright (C) 2011-2015, Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Print contact details |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+-----------------------------------------------------------------------+
*/
// Get contact ID and source ID from request
$cids = rcmail_get_cids();
$source = key($cids);
$cid = $cids ? array_shift($cids[$source]) : null;
// Initialize addressbook source
$CONTACTS = rcmail_contact_source($source, true);
$SOURCE_ID = $source;
// read contact record
if ($cid && $CONTACTS) {
$record = $CONTACTS->get_record($cid, true);
}
$OUTPUT->add_handlers(array(
'contacthead' => 'rcmail_contact_head',
'contactdetails' => 'rcmail_contact_details',
'contactphoto' => 'rcmail_contact_photo',
));
$OUTPUT->send('contactprint');
function rcmail_contact_head($attrib)
{
global $CONTACTS, $RCMAIL;
// check if we have a valid result
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
$RCMAIL->output->show_message('contactnotfound', 'error');
return false;
}
$form = array(
'head' => array( // section 'head' is magic!
'name' => $RCMAIL->gettext('contactnameandorg'),
'content' => array(
'prefix' => array(),
'name' => array(),
'firstname' => array(),
'middlename' => array(),
'surname' => array(),
'suffix' => array(),
),
),
);
unset($attrib['name']);
return rcmail_contact_form($form, $record, $attrib);
}
function rcmail_contact_details($attrib)
{
global $CONTACTS, $RCMAIL, $CONTACT_COLTYPES;
// check if we have a valid result
if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) {
return false;
}
$i_size = !empty($attrib['size']) ? $attrib['size'] : 40;
$form = array(
'contact' => array(
'name' => $RCMAIL->gettext('properties'),
'content' => array(
'organization' => array(),
'department' => array(),
'jobtitle' => array(),
'email' => array(),
'phone' => array(),
'address' => array(),
'website' => array(),
'im' => array(),
'groups' => array('value' => 'sdfsdfs', 'label' => $RCMAIL->gettext('groups')),
),
),
'personal' => array(
'name' => $RCMAIL->gettext('personalinfo'),
'content' => array(
'nickname' => array(),
'gender' => array(),
'maidenname' => array(),
'birthday' => array(),
'anniversary' => array(),
'manager' => array(),
'assistant' => array(),
'spouse' => array(),
),
),
);
if (isset($CONTACT_COLTYPES['notes'])) {
$form['notes'] = array(
'name' => $RCMAIL->gettext('notes'),
'content' => array(
'notes' => array('type' => 'textarea', 'label' => false),
),
);
}
if ($CONTACTS->groups) {
$groups = $CONTACTS->get_record_groups($record['ID']);
if (!empty($groups)) {
$form['contact']['content']['groups'] = array(
'value' => rcube::Q(implode(', ', $groups)),
'label' => $RCMAIL->gettext('groups')
);
}
}
return rcmail_contact_form($form, $record);
}

@ -66,11 +66,16 @@ function rcmail_contact_head($attrib)
'head' => array( // section 'head' is magic!
'name' => $RCMAIL->gettext('contactnameandorg'),
'content' => array(
'prefix' => array('type' => 'text'),
'firstname' => array('type' => 'text'),
'middlename' => array('type' => 'text'),
'surname' => array('type' => 'text'),
'suffix' => array('type' => 'text'),
'prefix' => array('type' => 'text'),
'firstname' => array('type' => 'text'),
'middlename' => array('type' => 'text'),
'surname' => array('type' => 'text'),
'suffix' => array('type' => 'text'),
'name' => array('type' => 'text'),
'nickname' => array('type' => 'text'),
'organization' => array('type' => 'text'),
'department' => array('type' => 'text'),
'jobtitle' => array('type' => 'text'),
),
),
);

@ -43,6 +43,16 @@
background-position: -32px -32px;
}
#abooktoolbar a.print {
background: url(images/mail_toolbar.png) 0 0 no-repeat transparent;
background-position: -256px 0;
}
#abooktoolbar a.printSel {
background: url(images/mail_toolbar.png) 0 0 no-repeat transparent;
background-position: -256px -32px;
}
#abooktoolbar a.delete {
background-position: -64px 0;
}

@ -159,3 +159,67 @@ p.image-attachment .attachment-links
{
display: none;
}
/* contact print */
#contact-details fieldset {
color: #666;
border: 1px solid #999;
margin-top: 5px;
}
#contact-details fieldset.contactfieldgroup {
border: 0;
padding: 0;
margin: 0;
}
#contact-details div.row {
padding: 2px 0;
}
#contact-details .contactfieldlabel {
display: inline-block;
vertical-align: top;
width: 150px;
overflow: hidden;
text-overflow: ellipsis;
}
#contact-details .contactfieldcontent {
display: inline-block;
vertical-align: top;
font-weight: bold;
}
#contact-details #contactphoto {
float: left;
margin: 5px 15px 5px 3px;
width: 112px;
border: 0;
padding: 0;
}
#contact-details #contactpic {
width: 112px;
background: white;
}
#contact-details #contactpic img {
max-width: 112px;
visibility: inherit;
}
#contact-details #contacthead {
border: 0;
margin: 0 16em 0 0;
padding: 0;
}
#contact-details #contacthead > legend {
display: none;
}
#contact-details #contacthead .names span.namefield {
font-size: 140%;
font-weight: bold;
}

@ -21,6 +21,7 @@
<div id="abooktoolbar">
<roundcube:button command="add" type="link" class="buttonPas addcontact" classAct="button addcontact" classSel="button addcontactSel" title="newcontact" content=" " />
<roundcube:button command="compose" type="link" class="buttonPas compose" classAct="button compose" classSel="button composeSel" title="composeto" content=" " />
<roundcube:button command="print" type="link" class="buttonPas print" classAct="button print" classSel="button printSel" label="print" title="printcontact" content=" " />
<roundcube:button command="delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="deletecontact" content=" " />
<span class="separator">&nbsp;</span>
<roundcube:button command="import" type="link" class="buttonPas import" classAct="button import" classSel="button importSel" title="importcontacts" content=" " />

@ -0,0 +1,20 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><roundcube:object name="pagetitle" /></title>
<link rel="shortcut icon" href="/images/favicon.ico"/>
<link rel="stylesheet" type="text/css" href="/print.css" />
</head>
<body>
<roundcube:object name="logo" src="/images/roundcube_logo.png" id="logo" border="0" />
<div id="contact-details">
<div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" placeholderGroup="/images/contactgroup.png" /></div>
<roundcube:object name="contacthead" id="contacthead" />
<div style="clear:both"></div>
<roundcube:object name="contactdetails" />
</div>
</body>
</html>

@ -143,3 +143,66 @@ p.image-attachment .attachment-links {
display: none;
}
/* contact print */
#contact-details fieldset {
color: #666;
border: 1px solid #999;
margin-top: 5px;
}
#contact-details fieldset.contactfieldgroup {
border: 0;
padding: 0;
margin: 0;
}
#contact-details div.row {
padding: 2px 0;
}
#contact-details .contactfieldlabel {
display: inline-block;
vertical-align: top;
width: 150px;
overflow: hidden;
text-overflow: ellipsis;
}
#contact-details .contactfieldcontent {
display: inline-block;
vertical-align: top;
font-weight: bold;
}
#contact-details #contactphoto {
float: left;
margin: 5px 15px 5px 3px;
width: 112px;
border: 0;
padding: 0;
}
#contact-details #contactpic {
width: 112px;
background: white;
}
#contact-details #contactpic img {
max-width: 112px;
visibility: inherit;
}
#contact-details #contacthead {
border: 0;
margin: 0 16em 0 0;
padding: 0;
}
#contact-details #contacthead > legend {
display: none;
}
#contact-details #contacthead .names span.namefield {
font-size: 140%;
font-weight: bold;
}

@ -23,6 +23,7 @@
<span class="spacer"></span>
<roundcube:button command="compose" type="link" class="button compose disabled" classAct="button compose" classSel="button compose pressed" label="compose" title="writenewmessage" />
<roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" title="printcontact" />
<roundcube:button command="advanced-search" type="link" class="button search disabled" classAct="button search" classSel="button search pressed" label="advanced" title="advsearch" />
<roundcube:container name="toolbar" id="addressbooktoolbar" />

@ -0,0 +1,20 @@
<roundcube:object name="doctype" value="html5" />
<html>
<head>
<title><roundcube:object name="pagetitle" /></title>
<link rel="shortcut icon" href="/images/favicon.ico"/>
<link rel="stylesheet" type="text/css" href="/print.css" />
</head>
<body>
<div id="header"><roundcube:object name="logo" src="/images/roundcube_logo.png" id="toplogo" border="0" alt="Logo" /></div>
<div id="contact-details" class="boxcontent">
<div id="contactphoto"><roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" placeholderGroup="/images/contactgroup.png" /></div>
<roundcube:object name="contacthead" id="contacthead" />
<br style="clear:both" />
<roundcube:object name="contactdetails" />
</div>
</body>
</html>
Loading…
Cancel
Save