Merge branch 'move_addressbook' of https://github.com/johndoh/roundcubemail into johndoh-move_addressbook

pull/6144/head
Aleksander Machniak 7 years ago
commit eb0228ba86

@ -19,4 +19,5 @@ $labels['addvcardmsg'] = 'Add vCard to addressbook';
$labels['vcardsavefailed'] = 'Unable to save vCard';
$labels['attachvcard'] = 'Attach vCard';
$labels['vcard'] = 'vCard';
$labels['forwardvcard'] = 'Forward vCard';
?>

@ -22,5 +22,6 @@ $labels['vcardsavefailed'] = 'Unable to save vCard';
$labels['attachvcard'] = 'Attach vCard';
$labels['vcardattached'] = 'vCard file attached.';
$labels['vcard'] = 'vCard';
$labels['forwardvcard'] = 'Forward vCard';
?>

@ -39,3 +39,8 @@ p.vcardattachment button {
.messagelist tr .attachment span.attachment.vcard {
background: url(vcard.png) 0 center no-repeat;
}
#contactmenu li a.vcard {
background: url(../../../../skins/classic/images/messageicons.png) no-repeat 7px 0;
background-position: 6px -168px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

@ -33,3 +33,8 @@ a.listbutton.vcard .inner
.messagelist tbody tr .attachment span.attachment.vcard {
background: url(vcard.png) 0 center no-repeat;
}
ul.toolbarmenu li span.vcard {
background: url(listicons.png) no-repeat 7px 0;
background-position: 0 -3px;
}

@ -9,7 +9,7 @@
*/
class vcard_attachments extends rcube_plugin
{
public $task = 'mail';
public $task = 'mail|addressbook';
private $message;
private $vcard_parts = array();
@ -19,37 +19,57 @@ class vcard_attachments extends rcube_plugin
{
$rcmail = rcmail::get_instance();
if ($rcmail->action == 'show' || $rcmail->action == 'preview') {
$this->add_hook('message_load', array($this, 'message_load'));
$this->add_hook('message_objects', array($this, 'message_objects'));
$this->add_hook('template_object_messagebody', array($this, 'html_output'));
}
else if ($rcmail->action == 'upload') {
$this->add_hook('attachment_from_uri', array($this, 'attach_vcard'));
}
else if ($rcmail->action == 'compose' && !$rcmail->output->framed) {
if ($rcmail->task == 'addressbook') {
$skin_path = $this->local_skin_path();
$btn_class = strpos($skin_path, 'classic') ? 'button' : 'listbutton';
$this->add_texts('localization', true);
$this->include_stylesheet($skin_path . '/style.css');
$this->include_script('vcardattach.js');
$this->add_button(
array(
'type' => 'link',
'label' => 'vcard_attachments.vcard',
'type' => 'link-menuitem',
'label' => 'vcard_attachments.forwardvcard',
'command' => 'attach-vcard',
'class' => $btn_class . ' vcard disabled',
'classact' => $btn_class . ' vcard',
'title' => 'vcard_attachments.attachvcard',
'innerclass' => 'inner',
'class' => 'icon vcard',
'classact' => 'icon vcard active',
'innerclass' => 'icon vcard',
),
'compose-contacts-toolbar');
'contactmenu');
}
else if (!$rcmail->output->framed && (!$rcmail->action || $rcmail->action == 'list')) {
$skin_path = $this->local_skin_path();
$this->include_stylesheet($skin_path . '/style.css');
$this->include_script('vcardattach.js');
else {
if ($rcmail->action == 'show' || $rcmail->action == 'preview') {
$this->add_hook('message_load', array($this, 'message_load'));
$this->add_hook('message_objects', array($this, 'message_objects'));
$this->add_hook('template_object_messagebody', array($this, 'html_output'));
}
else if ($rcmail->action == 'upload') {
$this->add_hook('attachment_from_uri', array($this, 'attach_vcard'));
}
else if ($rcmail->action == 'compose' && !$rcmail->output->framed) {
$skin_path = $this->local_skin_path();
$btn_class = strpos($skin_path, 'classic') ? 'button' : 'listbutton';
$this->add_texts('localization', true);
$this->include_stylesheet($skin_path . '/style.css');
$this->include_script('vcardattach.js');
$this->add_button(
array(
'type' => 'link',
'label' => 'vcard_attachments.vcard',
'command' => 'attach-vcard',
'class' => $btn_class . ' vcard disabled',
'classact' => $btn_class . ' vcard',
'title' => 'vcard_attachments.attachvcard',
'innerclass' => 'inner',
),
'compose-contacts-toolbar');
$this->add_hook('message_compose', array($this, 'message_compose'));
}
else if (!$rcmail->output->framed && (!$rcmail->action || $rcmail->action == 'list')) {
$skin_path = $this->local_skin_path();
$this->include_stylesheet($skin_path . '/style.css');
$this->include_script('vcardattach.js');
}
}
$this->register_action('plugin.savevcard', array($this, 'save_vcard'));
@ -129,6 +149,20 @@ class vcard_attachments extends rcube_plugin
return $p;
}
/**
* This callback function adds a vCard to the message when attached from the Address book
*/
function message_compose($p)
{
if (rcube_utils::get_input_value('_attach_vcard', rcube_utils::INPUT_GET) == '1' && ($uri = rcube_utils::get_input_value('_uri', rcube_utils::INPUT_GET))) {
if ($attachment = $this->attach_vcard(array('compose_id' => $p['compose_id'], 'uri' => $uri))) {
$p['attachments'][] = $attachment;
};
}
return $p;
}
/**
* This callback function removes message part's content
* for parts that are vcards
@ -268,7 +302,7 @@ class vcard_attachments extends rcube_plugin
public function attach_vcard($args)
{
if (preg_match('|^vcard://(.+)$|', $args['uri'], $m)) {
list($cid, $source) = explode('-', $m[1]);
list($source, $cid, $email) = explode('-', $m[1]);
$vcard = $this->get_contact_vcard($source, $cid, $filename);
$params = array(

@ -34,13 +34,19 @@ function plugin_vcard_attach()
{
var id, n, contacts = [],
ts = new Date().getTime(),
args = {_uploadid: ts, _id: rcmail.env.compose_id},
args = {_uploadid: ts, _id: rcmail.env.compose_id || null},
selection = rcmail.contact_list.get_selection();
for (n=0; n < selection.length; n++) {
id = selection[n];
if (id && id.charAt(0) != 'E' && rcmail.env.contactdata[id])
contacts.push(id);
if (rcmail.env.task == 'addressbook') {
id = selection[n];
contacts.push(rcmail.env.source + '-' + id + '-0');
}
else {
id = selection[n];
if (id && id.charAt(0) != 'E' && rcmail.env.contactdata[id])
contacts.push(id);
}
}
if (!contacts.length)
@ -48,19 +54,27 @@ function plugin_vcard_attach()
args._uri = 'vcard://' + contacts.join(',');
// add to attachments list
if (!rcmail.add2attachment_list(ts, {name: '', html: rcmail.get_label('attaching'), classname: 'uploading', complete: false}))
rcmail.file_upload_id = rcmail.set_busy(true, 'attaching');
if (rcmail.env.task == 'addressbook') {
args._attach_vcard = 1;
rcmail.open_compose_step(args);
}
else {
// add to attachments list
if (!rcmail.add2attachment_list(ts, {name: '', html: rcmail.get_label('attaching'), classname: 'uploading', complete: false}))
rcmail.file_upload_id = rcmail.set_busy(true, 'attaching');
rcmail.http_post('upload', args);
rcmail.http_post('upload', args);
}
}
window.rcmail && rcmail.addEventListener('init', function(evt) {
if (rcmail.gui_objects.messagelist)
rcmail.addEventListener('insertrow', function(data, evt) { plugin_vcard_insertrow(data); });
if (rcmail.env.action == 'compose' && rcmail.gui_objects.contactslist) {
rcmail.env.compose_commands.push('attach-vcard');
if ((rcmail.env.action == 'compose' || (rcmail.env.task == 'addressbook' && rcmail.env.action == '')) && rcmail.gui_objects.contactslist) {
if (rcmail.env.action == 'compose')
rcmail.env.compose_commands.push('attach-vcard');
rcmail.register_command('attach-vcard', function() { plugin_vcard_attach(); });
rcmail.contact_list.addEventListener('select', function(list) {
// TODO: support attaching more than one at once

@ -47,6 +47,7 @@ function rcube_webmail()
this.group2expand = {};
this.http_request_jobs = {};
this.menu_stack = [];
this.entity_selectors = [];
// webmail client settings
this.dblclick_time = 500;
@ -979,14 +980,14 @@ function rcube_webmail()
if (this.task == 'mail')
this.move_messages(props, event);
else if (this.task == 'addressbook')
this.move_contacts(props);
this.move_contacts(props, event);
break;
case 'copy':
if (this.task == 'mail')
this.copy_messages(props, event);
else if (this.task == 'addressbook')
this.copy_contacts(props);
this.copy_contacts(props, event);
break;
case 'mark':
@ -1233,7 +1234,7 @@ function rcube_webmail()
case 'print':
if (this.task == 'addressbook') {
if (uid = this.contact_list.get_single_selection()) {
if (uid = this.get_single_cid()) {
url = '&_action=print&_cid=' + uid;
if (this.env.source)
url += '&_source=' + urlencode(this.env.source);
@ -5903,15 +5904,21 @@ function rcube_webmail()
}
this.env.selection_sources = $.unique(this.env.selection_sources);
var groupcount = 0;
if (source.groups)
$.each(this.env.contactgroups, function(){ if (this.source === ref.env.source) groupcount++ });
}
// 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-assign-selected', groupcount > 0 && selected && writable);
this.enable_command('group-remove-selected', this.env.group && selected && writable);
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', selected && writable);
this.enable_command('qrcode', selected == 1);
return false;
};
@ -5953,6 +5960,9 @@ function rcube_webmail()
this.env.address_group_stack = index < 0 ? [] : this.env.address_group_stack.slice(0, index);
// remove cached contact group selector
this.destroy_entity_selector('contactgroup-selector');
// make sure the current group is on top of the stack
if (this.env.group) {
if (!search) search = {};
@ -6130,8 +6140,15 @@ function rcube_webmail()
};
// copy contact(s) to the specified target (group or directory)
this.copy_contacts = function(to)
this.copy_contacts = function(to, event)
{
if (!to) {
return this.addressbook_selector(event, function(to, obj) {
var to = $(obj).data('source') ? ref.env.contactgroups['G' + $(obj).data('source') + $(obj).data('gid')] : ref.env.address_sources[to];
ref.command('copy', to);
});
}
var dest = to.type == 'group' ? to.source : to.id,
source = this.env.source,
group = this.env.group ? this.env.group : '',
@ -6164,8 +6181,15 @@ function rcube_webmail()
};
// move contact(s) to the specified target (group or directory)
this.move_contacts = function(to)
this.move_contacts = function(to, event)
{
if (!to) {
return this.addressbook_selector(event, function(to, obj) {
var to = $(obj).data('source') ? ref.env.contactgroups['G' + $(obj).data('source') + $(obj).data('gid')] : ref.env.address_sources[to];
ref.command('move', to);
});
}
var dest = to.type == 'group' ? to.source : to.id,
source = this.env.source,
group = this.env.group ? this.env.group : '';
@ -6392,6 +6416,10 @@ function rcube_webmail()
var key = 'G'+prop.source+prop.id;
if (this.treelist.remove(key)) {
// make sure there is no cached address book or contact group selectors
this.destroy_entity_selector('addressbook-selector');
this.destroy_entity_selector('contactgroup-selector');
this.triggerEvent('group_delete', { source:prop.source, id:prop.id });
delete this.env.contactfolders[key];
delete this.env.contactgroups[key];
@ -6401,6 +6429,12 @@ function rcube_webmail()
this.list_contacts(prop.source, 0);
};
//assign selected contacts to a group
this.group_assign_selected = function(props, obj, event)
{
this.contactgroup_selector(event, function(to) { ref.group_member_change('add', ref.contact_list.get_selection(), ref.env.source, to); });
};
//remove selected contacts from current active group
this.group_remove_selected = function()
{
@ -6416,6 +6450,7 @@ function rcube_webmail()
for (n=0; n<selection.length; n++) {
id = selection[n];
this.contact_list.remove_row(id, (n == selection.length-1));
this.contact_list.clear_selection();
}
}
};
@ -6434,6 +6469,10 @@ function rcube_webmail()
this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup');
// make sure there is no cached address book or contact group selectors
this.destroy_entity_selector('addressbook-selector');
this.destroy_entity_selector('contactgroup-selector');
this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
};
@ -6476,6 +6515,10 @@ function rcube_webmail()
// update list node and re-sort it
this.treelist.update(key, newnode, true);
// make sure there is no cached address book or contact group selectors
this.destroy_entity_selector('addressbook-selector');
this.destroy_entity_selector('contactgroup-selector');
this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key), newid:prop.newid });
};
@ -6834,7 +6877,7 @@ function rcube_webmail()
options = {button: false, cancel_button: 'close', width: 300, height: 300},
img = new Image(300, 300);
img.src = this.url('addressbook/qrcode', {_source: this.env.source, _cid: this.env.cid});
img.src = this.url('addressbook/qrcode', {_source: this.env.source, _cid: this.get_single_cid()});
return this.simple_dialog(img, title, null, options);
};
@ -8174,48 +8217,113 @@ function rcube_webmail()
elem.onclick = function() { ref.command('show-headers', '', elem); };
};
// create folder selector popup, position and display it
// create folder selector popup
this.folder_selector = function(event, callback)
{
var container = this.folder_selector_element;
this.entity_selector('folder-selector', callback, this.env.mailboxes_list, function(obj, a) {
var n = 0, s = 0,
delim = ref.env.delimiter,
folder = ref.env.mailboxes[obj],
id = folder.id,
row = $('<li>');
if (!container) {
var rows = [],
delim = this.env.delimiter,
ul = $('<ul class="toolbarmenu">'),
link = document.createElement('a');
if (folder.virtual)
a.addClass('virtual').attr({'aria-disabled': 'true', tabindex: '-1'});
else
a.addClass('active').data('id', folder.id);
container = $('<div id="folder-selector" class="popupmenu"></div>');
link.href = '#';
link.className = 'icon';
if (folder['class'])
row.addClass(folder['class']);
// loop over sorted folders list
$.each(this.env.mailboxes_list, function() {
var n = 0, s = 0,
folder = ref.env.mailboxes[this],
id = folder.id,
a = $(link.cloneNode(false)).attr('rel', folder.id),
row = $('<li>');
// calculate/set indentation level
while ((s = id.indexOf(delim, s)) >= 0) {
n++; s++;
}
a.css('padding-left', n ? (n * 16) + 'px' : 0);
if (folder.virtual)
a.addClass('virtual').attr({'aria-disabled': 'true', tabindex: '-1'});
else
a.addClass('active').data('id', folder.id);
// add folder name element
a.append($('<span>').text(folder.name));
return row.append(a);
}, event);
};
// create addressbook selector popup
this.addressbook_selector = function(event, callback)
{
// build addressbook + groups list
var combined_sources = [];
if (folder['class'])
row.addClass(folder['class']);
// check we really need it before processing
if (!this.entity_selectors['addressbook-selector']) {
$.each(this.env.address_sources, function() {
if (!this.readonly) {
var source = this;
combined_sources.push(source);
// calculate/set indentation level
while ((s = id.indexOf(delim, s)) >= 0) {
n++; s++;
$.each(ref.env.contactgroups, function() {
if (source.id === this.source) {
combined_sources.push(this);
}
});
}
a.css('padding-left', n ? (n * 16) + 'px' : 0);
});
}
this.entity_selector('addressbook-selector', callback, combined_sources, function(obj, a) {
var row = $('<li>');
if (obj.type == 'group') {
a.attr('rel', this.source + ':' + this.id);
a.addClass('contactgroup');
a.data('source', this.source).data('gid', this.id);
a.addClass('active').data('id', this.source + ':' + this.id);
a.css('padding-left', '16px');
}
else {
a.addClass('addressbook');
a.addClass('active').data('id', obj.id);
}
a.append($('<span>').text(obj.name));
// add folder name element
a.append($('<span>').text(folder.name));
return row.append(a);
}, event);
};
row.append(a);
rows.push(row);
// create contactgroup selector popup
this.contactgroup_selector = function(event, callback)
{
this.entity_selector('contactgroup-selector', callback, this.env.contactgroups, function(obj, a) {
if (ref.env.source === obj.source) {
var row = $('<li>');
a.addClass('contactgroup');
a.addClass('active').data('id', obj.id);
a.append($('<span>').text(obj.name));
return row.append(a);
}
}, event);
};
// create selector popup (eg for folders or address books), position and display it
this.entity_selector = function(name, click_callback, entity_list, list_callback, event)
{
var container = this.entity_selectors[name];
if (!container) {
var rows = [],
container = $('<div>').attr('id', name).addClass('popupmenu'),
ul = $('<ul>').addClass('toolbarmenu'),
link = document.createElement('a');
link.href = '#';
link.className = 'icon';
// loop over entity list
$.each(entity_list, function() {
var a = $(link.cloneNode(false)).attr('rel', this.id);
rows.push(list_callback(this, a));
});
ul.append(rows).appendTo(container);
@ -8230,18 +8338,23 @@ function rcube_webmail()
// register delegate event handler for folder item clicks
container.on('click', 'a.active', function(e) {
container.data('callback')($(this).data('id'));
container.data('callback')($(this).data('id'), this);
});
this.folder_selector_element = container;
this.entity_selectors[name] = container;
}
container.data('callback', callback);
container.data('callback', click_callback);
// position menu on the screen
this.show_menu('folder-selector', true, event);
this.show_menu(name, true, event);
};
this.destroy_entity_selector = function(name)
{
$("#" + name).remove();
delete this.entity_selectors[name];
};
/***********************************************/
/********* popup menu functions *********/

@ -381,6 +381,8 @@ $labels['newgroup'] = 'Create new group';
$labels['addgroup'] = 'Add group';
$labels['grouprename'] = 'Rename group';
$labels['groupdelete'] = 'Delete group';
$labels['groupassign'] = 'Assign to group...';
$labels['groupremove'] = 'Remove from group';
$labels['groupremoveselected'] = 'Remove selected contacts from group';
$labels['uponelevel'] = 'Up one level';
$labels['previouspage'] = 'Show previous set';
@ -608,6 +610,7 @@ $labels['arialabelmessageheaders'] = 'Message headers';
$labels['arialabelforwardingoptions'] = 'Forwarding options';
$labels['arialabelreplyalloptions'] = 'Reply-all options';
$labels['arialabelmoremessageactions'] = 'More message actions';
$labels['arialabelmorecontactactions'] = 'More contact actions';
$labels['arialabelmarkmessagesas'] = 'Mark selected messages as...';
$labels['arialabelcomposeoptions'] = 'Composition options';
$labels['arialabelresponsesmenu'] = 'Canned responses menu';

@ -441,6 +441,8 @@ $labels['newgroup'] = 'Create new group';
$labels['addgroup'] = 'Add group';
$labels['grouprename'] = 'Rename group';
$labels['groupdelete'] = 'Delete group';
$labels['groupassign'] = 'Assign to group...';
$labels['groupremove'] = 'Remove from group';
$labels['groupremoveselected'] = 'Remove selected contacts from group';
$labels['uponelevel'] = 'Up one level';
@ -692,6 +694,7 @@ $labels['arialabelmessageheaders'] = 'Message headers';
$labels['arialabelforwardingoptions'] = 'Forwarding options';
$labels['arialabelreplyalloptions'] = 'Reply-all options';
$labels['arialabelmoremessageactions'] = 'More message actions';
$labels['arialabelmorecontactactions'] = 'More contact actions';
$labels['arialabelmarkmessagesas'] = 'Mark selected messages as...';
$labels['arialabelcomposeoptions'] = 'Composition options';
$labels['arialabelresponsesmenu'] = 'Canned responses menu';

@ -131,7 +131,9 @@ $RCMAIL->register_action_map(array(
'search-delete' => 'search.inc',
));
// Disable qr-code if php-gd or Endroid's QrCode is not installed
$OUTPUT->set_env('qrcode', function_exists('imagecreate') && class_exists('Endroid\QrCode\QrCode'));
$OUTPUT->add_label('qrcode');
// instantiate a contacts object according to the given source
function rcmail_contact_source($source=null, $init_env=false, $writable=false)

@ -42,10 +42,6 @@ if ($cid && ($record = ($CONTACT_RECORD ?: $CONTACTS->get_record($cid, true))))
// get address book name (for display)
rcmail_set_sourcename($CONTACTS);
// Disable qr-code if php-gd or Endroid's QrCode is not installed
$OUTPUT->set_env('qrcode', function_exists('imagecreate') && class_exists('Endroid\QrCode\QrCode'));
$OUTPUT->add_label('qrcode');
$OUTPUT->add_handlers(array(
'contacthead' => 'rcmail_contact_head',
'contactdetails' => 'rcmail_contact_details',

@ -104,7 +104,8 @@ else if (!empty($result) && $result->count > 0) {
// add record for every email address of the contact
$emails = $CONTACTS->get_col_values('email', $row, true);
foreach ($emails as $i => $email) {
$row_id = $row['ID'].'-'.$i;
$source = $row['sourceid'] ?: $source;
$row_id = $source.'-'.$row['ID'].'-'.$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
$classname = $row['_type'] == 'group' ? 'group' : 'person';
$keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';

@ -84,7 +84,7 @@ if (!empty($result) && $result->count > 0) {
// (same as in list_contacts.inc)
$emails = $source->get_col_values('email', $row, true);
foreach ($emails as $i => $email) {
$row_id = $row['ID'].'-'.$i;
$row_id = $row['sourceid'].'-'.$row['ID'].'-'.$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
$title = rcube_addressbook::compose_search_name($row, $email, $name);

@ -92,6 +92,45 @@
background-position: -170px -32px;
}
#abooktoolbar a.contactmenu {
background: url(images/mail_toolbar.png) 0 0 no-repeat transparent;
background-position: -320px 0;
width: 34px;
}
#contactmenu li a
{
background: url(images/contactactions.png) no-repeat 7px 0;
background-position: 7px 20px;
}
#contactmenu li a.qrcode
{
background-position: 7px -39px;
}
#contactmenu li a.assigngroup
{
background-position: 7px 0;
}
#contactmenu li a.removegroup
{
background-position: 7px -19px;
}
#contactmenu li a.movelink
{
background: url(images/messageactions.png) no-repeat 7px 0;
background-position: 6px -160px;
}
#contactmenu li a.copylink
{
background: url(images/messageactions.png) no-repeat 7px 0;
background-position: 6px -142px;
}
#abookcountbar
{
margin-top: 4px;
@ -142,7 +181,9 @@
}
#directorylist li a,
#savedsearchlist li a
#savedsearchlist li a,
#addressbook-selector li a,
#contactgroup-selector li a
{
cursor: default;
display: block;
@ -200,6 +241,23 @@
background-position: 6px -162px;
}
#addressbook-selector li a.addressbook
{
padding-left: 25px;
}
#addressbook-selector li a.contactgroup
{
padding-left: 45px !important;
background-position: 25px -143px;
}
#contactgroup-selector li a
{
padding-left: 25px;
background-position: 5px -143px;
}
#contacts-table
{
width: 100%;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -31,6 +31,7 @@
</span>
<roundcube:button command="advanced-search" type="link" class="buttonPas search" classAct="button search" classSel="button searchSel" title="advsearch" content=" " />
<roundcube:container name="toolbar" id="abooktoolbar" />
<roundcube:button name="contactmenulink" id="contactmenulink" type="link" class="button contactmenu" title="moreactions" onclick="rcmail_ui.show_popup('contactmenu');return false" content=" " />
</div>
<div id="quicksearchbar">
@ -56,6 +57,21 @@
</ul>
</div>
<div id="contactmenu" class="popupmenu">
<ul class="toolbarmenu" id="contactmenumenu">
<roundcube:if condition="env:qrcode" />
<roundcube:button type="link-menuitem" class="qrcode" command="qrcode" label="qrcode" classAct="qrcode active" />
<roundcube:endif />
<roundcube:button type="link-menuitem" class="assigngroup" command="group-assign-selected" label="groupassign" classAct="assigngroup active" innerclass="folder-selector-link" />
<roundcube:button type="link-menuitem" class="removegroup" command="group-remove-selected" label="groupremove" classAct="removegroup active" />
<roundcube:if condition="env:writable_source &gt; 1" />
<roundcube:button type="link-menuitem" class="movelink" command="move" label="moveto" classAct="movelink active" innerclass="folder-selector-link" />
<roundcube:button type="link-menuitem" class="copylink" command="copy" label="copyto" classAct="copylink active" innerclass="folder-selector-link" />
<roundcube:endif />
<roundcube:container name="contactmenu" id="contactmenumenu" />
</ul>
</div>
<div id="mainscreen">
<div id="directorylistbox">
@ -107,7 +123,6 @@
<ul>
<li><roundcube:button command="group-rename" type="link" label="grouprename" classAct="active" /></li>
<li><roundcube:button command="group-delete" type="link" label="groupdelete" classAct="active" /></li>
<li><roundcube:button command="group-remove-selected" type="link" label="groupremoveselected" classAct="active" /></li>
<li class="separator_above"><roundcube:button command="search-create" type="link" label="searchsave" classAct="active" /></li>
<li><roundcube:button command="search-delete" type="link" label="searchdelete" classAct="active" /></li>
<roundcube:container name="groupoptions" id="groupoptionsmenu" />

@ -21,9 +21,6 @@
</div>
<p>
<roundcube:button command="edit" type="input" class="button" label="editcontact" condition="!ENV:readonly" />
<roundcube:if condition="env:qrcode" />
<roundcube:button command="qrcode" type="input" class="button" label="qrcode" />
<roundcube:endif />
</p>
</div>
<script type="text/javascript">rcube_init_tabs('contacttabs')</script>

@ -403,3 +403,41 @@ a.deletebutton {
#import-box .propform {
max-width: 50em;
}
ul.toolbarmenu li span.qrcode {
background-position: 0 -2408px;
}
ul.toolbarmenu li span.assigngroup {
background-position: 0 -2358px;
}
ul.toolbarmenu li span.removegroup {
background-position: 0 -2384px;
}
#addressbook-selector li a,
#contactgroup-selector li a {
padding-left: 2px;
}
#addressbook-selector li a span,
#contactgroup-selector li a span {
background: url(images/listicons.png) 4px 20px no-repeat;
display: block;
height: 17px;
min-height: 14px;
padding: 4px 4px 1px 28px;
overflow: hidden;
max-width: 120px;
text-overflow: ellipsis;
}
#addressbook-selector li a.addressbook span {
background-position: 4px -2222px;
}
#addressbook-selector li a.contactgroup span,
#contactgroup-selector li a.contactgroup span {
background-position: 4px -2245px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@ -26,6 +26,7 @@
<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" />
<roundcube:button name="contactmenulink" id="contactmenulink" type="link" class="button more" label="more" title="moreactions" onclick="UI.toggle_popup('contactmenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="contactmenu-menu" />
<div id="exportmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-exportmenu" class="voice"><roundcube:label name="arialabelcontactexportoptions" /></h3>
@ -35,6 +36,21 @@
</ul>
</div>
<div id="contactmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-contactmenu" class="voice"><roundcube:label name="arialabelmorecontactactions" /></h3>
<ul id="contactmenu-menu" class="toolbarmenu iconized" role="menu" aria-labelledby="aria-label-contactmenu">
<roundcube:if condition="env:qrcode" />
<roundcube:button type="link-menuitem" command="qrcode" label="qrcode" class="icon" classAct="icon active" innerclass="icon qrcode" />
<roundcube:endif />
<roundcube:button type="link-menuitem" command="group-assign-selected" label="groupassign" class="icon" classAct="icon active" innerclass="icon assigngroup folder-selector-link" />
<roundcube:button type="link-menuitem" command="group-remove-selected" label="groupremove" class="icon" classAct="icon active" innerclass="icon removegroup" />
<roundcube:if condition="env:writable_source &gt; 1" />
<roundcube:button type="link-menuitem" command="move" label="moveto" class="icon" classAct="icon active" innerclass="icon move folder-selector-link" />
<roundcube:button type="link-menuitem" command="copy" label="copyto" class="icon" classAct="icon active" innerclass="icon copy folder-selector-link" />
<roundcube:endif />
<roundcube:container name="contactmenu" id="contactmenu-menu" />
</ul>
</div>
</div>
<!-- search box -->
@ -103,7 +119,7 @@
<roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" label="last" />
</div>
<div class="boxfooter">
<roundcube:button command="add" type="link" title="newcontact" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="addcontact" /><roundcube:button command="delete" type="link" title="deletecontact" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="deletecontact" /><roundcube:button command="group-remove-selected" type="link" title="groupremoveselected" class="listbutton removegroup disabled" classAct="listbutton removegroup" innerClass="inner" label="groupremoveselected" />
<roundcube:button command="add" type="link" title="newcontact" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="addcontact" /><roundcube:button command="delete" type="link" title="deletecontact" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="deletecontact" />
<span class="countdisplay" aria-live="polite" aria-relevant="text">
<span class="voice"><roundcube:label name="contacts" /></span>
<roundcube:object name="recordsCountDisplay" label="fromtoshort" />

@ -25,9 +25,6 @@
<div id="headerbuttons" class="formbuttons">
<roundcube:button command="edit" type="input" class="button mainaction" label="editcontact" condition="!ENV:readonly" />
<roundcube:if condition="env:qrcode" />
<roundcube:button command="qrcode" type="input" class="button" label="qrcode" />
<roundcube:endif />
</div>
<roundcube:include file="/includes/footer.html" />

Loading…
Cancel
Save