Implemented menu actions to copy/move messages, added folder-selector widget (#1484086)

pull/158/merge
Aleksander Machniak 11 years ago
parent 4187b3e26f
commit 9a0153324e

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Implemented menu actions to copy/move messages, added folder-selector widget (#1484086)
- Fix regression where only first new folder was placed in correct place on the list (#1489472) - Fix regression where only first new folder was placed in correct place on the list (#1489472)
- Fix issue where children of selected and collapsed thread were skipped on various actions (#1489457) - Fix issue where children of selected and collapsed thread were skipped on various actions (#1489457)
- Fix issue where groups were not deleted when "Replace entire addressbook" option on contacts import was used (#1489420) - Fix issue where groups were not deleted when "Replace entire addressbook" option on contacts import was used (#1489420)

@ -1282,15 +1282,24 @@ class rcmail extends rcube
} }
else { else {
$js_mailboxlist = array(); $js_mailboxlist = array();
$out = html::tag('ul', $attrib, $rcmail->render_folder_tree_html($a_mailboxes, $mbox_name, $js_mailboxlist, $attrib), html::$common_attrib); $tree = $rcmail->render_folder_tree_html($a_mailboxes, $mbox_name, $js_mailboxlist, $attrib);
if ($type != 'js') {
$out = html::tag('ul', $attrib, $tree, html::$common_attrib);
$rcmail->output->include_script('treelist.js'); $rcmail->output->include_script('treelist.js');
$rcmail->output->add_gui_object('mailboxlist', $attrib['id']); $rcmail->output->add_gui_object('mailboxlist', $attrib['id']);
$rcmail->output->set_env('mailboxes', $js_mailboxlist);
$rcmail->output->set_env('unreadwrap', $attrib['unreadwrap']); $rcmail->output->set_env('unreadwrap', $attrib['unreadwrap']);
$rcmail->output->set_env('collapsed_folders', (string)$rcmail->config->get('collapsed_folders')); $rcmail->output->set_env('collapsed_folders', (string)$rcmail->config->get('collapsed_folders'));
} }
$rcmail->output->set_env('mailboxes', $js_mailboxlist);
// we can't use object keys in javascript because they are unordered
// we need sorted folders list for folder-selector widget
$rcmail->output->set_env('mailboxes_list', array_keys($js_mailboxlist));
}
return $out; return $out;
} }
@ -1473,9 +1482,13 @@ class rcmail extends rcube
$jslist[$folder['id']] = array( $jslist[$folder['id']] = array(
'id' => $folder['id'], 'id' => $folder['id'],
'name' => $foldername, 'name' => $foldername,
'virtual' => $folder['virtual'] 'virtual' => $folder['virtual'],
); );
if (!empty($folder_class)) {
$jslist[$folder['id']]['class'] = $folder_class;
}
if (!empty($folder['folders'])) { if (!empty($folder['folders'])) {
$out .= html::tag('ul', array('style' => ($is_collapsed ? "display:none;" : null)), $out .= html::tag('ul', array('style' => ($is_collapsed ? "display:none;" : null)),
$this->render_folder_tree_html($folder['folders'], $mbox_name, $jslist, $attrib, $nestLevel+1)); $this->render_folder_tree_html($folder['folders'], $mbox_name, $jslist, $attrib, $nestLevel+1));

@ -842,14 +842,14 @@ function rcube_webmail()
case 'move': case 'move':
case 'moveto': // deprecated case 'moveto': // deprecated
if (this.task == 'mail') if (this.task == 'mail')
this.move_messages(props); this.move_messages(props, obj);
else if (this.task == 'addressbook') else if (this.task == 'addressbook')
this.move_contacts(props); this.move_contacts(props);
break; break;
case 'copy': case 'copy':
if (this.task == 'mail') if (this.task == 'mail')
this.copy_messages(props); this.copy_messages(props, obj);
else if (this.task == 'addressbook') else if (this.task == 'addressbook')
this.copy_contacts(props); this.copy_contacts(props);
break; break;
@ -1411,8 +1411,6 @@ function rcube_webmail()
this.drag_start = function(list) this.drag_start = function(list)
{ {
var model = this.task == 'mail' ? this.env.mailboxes : this.env.contactfolders;
this.drag_active = true; this.drag_active = true;
if (this.preview_timer) if (this.preview_timer)
@ -2612,10 +2610,12 @@ function rcube_webmail()
}; };
// copy selected messages to the specified mailbox // copy selected messages to the specified mailbox
this.copy_messages = function(mbox) this.copy_messages = function(mbox, obj)
{ {
if (mbox && typeof mbox === 'object') if (mbox && typeof mbox === 'object')
mbox = mbox.id; mbox = mbox.id;
else if (!mbox)
return this.folder_selector(obj, function(folder) { ref.command('copy', folder); });
// exit if current or no mailbox specified // exit if current or no mailbox specified
if (!mbox || mbox == this.env.mailbox) if (!mbox || mbox == this.env.mailbox)
@ -2632,10 +2632,12 @@ function rcube_webmail()
}; };
// move selected messages to the specified mailbox // move selected messages to the specified mailbox
this.move_messages = function(mbox) this.move_messages = function(mbox, obj)
{ {
if (mbox && typeof mbox === 'object') if (mbox && typeof mbox === 'object')
mbox = mbox.id; mbox = mbox.id;
else if (!mbox)
return this.folder_selector(obj, function(folder) { ref.command('move', folder); });
// exit if current or no mailbox specified // exit if current or no mailbox specified
if (!mbox || mbox == this.env.mailbox) if (!mbox || mbox == this.env.mailbox)
@ -6553,6 +6555,105 @@ function rcube_webmail()
elem.onclick = function() { rcmail.command('show-headers', '', elem); }; elem.onclick = function() { rcmail.command('show-headers', '', elem); };
}; };
// create folder selector popup, position and display it
this.folder_selector = function(obj, callback)
{
var container = this.folder_selector_element;
if (!container) {
var rows = [],
delim = this.env.delimiter,
ul = $('<ul class="toolbarmenu iconized">'),
li = document.createElement('li'),
link = document.createElement('a'),
span = document.createElement('span');
container = $('<div id="folder-selector" class="popupmenu"></div>');
link.href = '#';
link.className = 'icon';
// loop over sorted folders list
$.each(this.env.mailboxes_list, function() {
var tmp, n = 0, s = 0,
folder = ref.env.mailboxes[this],
id = folder.id,
a = link.cloneNode(false), row = li.cloneNode(false);
if (folder.virtual)
a.className += ' virtual';
else {
a.className += ' active';
a.onclick = function() { container.hide().data('callback')(folder.id); };
}
if (folder['class'])
a.className += ' ' + folder['class'];
// calculate/set indentation level
while ((s = id.indexOf(delim, s)) >= 0) {
n++; s++;
}
a.style.paddingLeft = n ? (n * 16) + 'px' : 0;
// add folder name element
tmp = span.cloneNode(false);
$(tmp).text(folder.name);
a.appendChild(tmp);
row.appendChild(a);
rows.push(row);
});
ul.append(rows).appendTo(container);
// temporarily show element to calculate its size
container.css({left: '-1000px', top: '-1000px'})
.appendTo($('body')).show();
// set max-height if the list is long
if (rows.length > 10)
container.css('max-height', $('li', container)[0].offsetHeight * 10 + 9)
// hide selector on click out of selector element
var fn = function(e) { if (e.target != container.get(0)) container.hide(); };
$(document.body).on('mouseup', fn);
$('iframe').contents().on('mouseup', fn)
.load(function(e) { try { $(this).contents().on('mouseup', fn); } catch(e) {}; });
this.folder_selector_element = container;
}
// position menu on the screen
this.element_position(container, obj);
container.show().data('callback', callback);
};
// position a menu element on the screen in relation to other object
this.element_position = function(element, obj)
{
var obj = $(obj), win = $(window),
width = obj.width(),
height = obj.height(),
win_height = win.height(),
elem_height = $(element).height(),
elem_width = $(element).width(),
pos = obj.offset(),
top = pos.top,
left = pos.left + width;
if (top + elem_height > win_height) {
top -= elem_height - height;
if (top < 0)
top = Math.max(0, (win_height - elem_height) / 2);
}
if (left + elem_width > win.width())
left -= elem_width + width;
element.css({left: left + 'px', top: top + 'px'});
};
/********************************************************/ /********************************************************/
/********* html to text conversion functions *********/ /********* html to text conversion functions *********/

@ -64,6 +64,7 @@ $labels['fromtoshort'] = '$from $to of $count';
$labels['copy'] = 'Copy'; $labels['copy'] = 'Copy';
$labels['move'] = 'Move'; $labels['move'] = 'Move';
$labels['moveto'] = 'Move to...'; $labels['moveto'] = 'Move to...';
$labels['copyto'] = 'Copy to...';
$labels['download'] = 'Download'; $labels['download'] = 'Download';
$labels['open'] = 'Open'; $labels['open'] = 'Open';
$labels['showattachment'] = 'Show'; $labels['showattachment'] = 'Show';

@ -965,6 +965,57 @@ ul.toolbarmenu li.separator_above
} }
/*** folder selector ***/
#folder-selector li a
{
padding: 0;
}
#folder-selector li a span
{
background: url(images/icons/folders.png) no-repeat 6px 0;
display: block;
height: 15px;
min-height: 14px;
padding: 2px 4px 2px 28px;
overflow: hidden;
max-width: 120px;
text-overflow: ellipsis;
}
#folder-selector li a.virtual
{
color: #A0A0A0;
}
#folder-selector li a.active:hover span
{
color: white;
}
#folder-selector li a.inbox span
{
background-position: 6px -18px;
}
#folder-selector li a.drafts span
{
background-position: 6px -37px;
}
#folder-selector li a.sent span
{
background-position: 6px -54px;
}
#folder-selector li a.trash span
{
background-position: 6px -91px;
}
#folder-selector li a.junk span
{
background-position: 6px -73px;
}
/***** tabbed interface elements *****/ /***** tabbed interface elements *****/
div.tabsbar, div.tabsbar,

@ -419,6 +419,7 @@ body_mouseup: function(evt, p)
&& !this.popups[i].toggle && !this.popups[i].toggle
&& (!this.popups[i].editable || !this.target_overlaps(target, this.popups[i].id)) && (!this.popups[i].editable || !this.target_overlaps(target, this.popups[i].id))
&& (!this.popups[i].sticky || !rcube_mouse_is_over(evt, rcube_find_object(this.popups[i].id))) && (!this.popups[i].sticky || !rcube_mouse_is_over(evt, rcube_find_object(this.popups[i].id)))
&& !$(target).is('.folder-selector-link') && !$(target).children('.folder-selector-link').length
) { ) {
window.setTimeout('rcmail_ui.show_popup("'+i+'",false);', 50); window.setTimeout('rcmail_ui.show_popup("'+i+'",false);', 50);
} }

@ -20,9 +20,6 @@
<roundcube:container name="toolbar" id="messagetoolbar" /> <roundcube:container name="toolbar" id="messagetoolbar" />
<roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');return false" content=" " /> <roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');return false" content=" " />
<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="moreactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " /> <roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="moreactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
<roundcube:if condition="template:name == 'message'" />
<roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('move', this.options[this.selectedIndex].value)" class="mboxlist" folder_filter="mail" />
<roundcube:endif />
</div> </div>
<div id="forwardmenu" class="popupmenu"> <div id="forwardmenu" class="popupmenu">
@ -46,6 +43,8 @@
<li><roundcube:button class="printlink" command="print" label="printmessage" classAct="printlink active" /></li> <li><roundcube:button class="printlink" command="print" label="printmessage" classAct="printlink active" /></li>
<li><roundcube:button class="downloadlink" command="download" label="emlsave" classAct="downloadlink active" /></li> <li><roundcube:button class="downloadlink" command="download" label="emlsave" classAct="downloadlink active" /></li>
<li><roundcube:button class="editlink" command="edit" prop="new" label="editasnew" classAct="editlink active" /></li> <li><roundcube:button class="editlink" command="edit" prop="new" label="editasnew" classAct="editlink active" /></li>
<li><roundcube:button class="movelink" command="move" label="moveto" classAct="copylink active" innerclass="folder-selector-link" /></li>
<li><roundcube:button class="copylink" command="copy" label="copyto" classAct="movelink active" innerclass="folder-selector-link" /></li>
<li class="separator_below"><roundcube:button class="sourcelink" command="viewsource" label="viewsource" classAct="sourcelink active" /></li> <li class="separator_below"><roundcube:button class="sourcelink" command="viewsource" label="viewsource" classAct="sourcelink active" /></li>
<li><roundcube:button class="openlink" command="open" label="openinextwin" target="_blank" classAct="openlink active" /></li> <li><roundcube:button class="openlink" command="open" label="openinextwin" target="_blank" classAct="openlink active" /></li>
<roundcube:container name="messagemenu" id="messagemenu" /> <roundcube:container name="messagemenu" id="messagemenu" />

@ -175,23 +175,6 @@
background-position: -512px 0; background-position: -512px 0;
} }
#messagetoolbar select.mboxlist
{
position: relative;
margin: 0 8px;
top: 7px;
}
#messagetoolbar select.mboxlist option
{
padding-left: 15px;
}
#messagetoolbar select.mboxlist option[value=""]
{
padding-left: 2px;
}
#messagemenu li a.active:hover, #messagemenu li a.active:hover,
#attachmentmenu li a.active:hover, #attachmentmenu li a.active:hover,
#markmessagemenu li a.active:hover #markmessagemenu li a.active:hover

@ -30,11 +30,13 @@
<div id="mailboxlist-container"> <div id="mailboxlist-container">
<div id="mailboxlist-title" class="boxtitle"><roundcube:label name="mailboxlist" /></div> <div id="mailboxlist-title" class="boxtitle"><roundcube:label name="mailboxlist" /></div>
<div class="boxlistcontent"> <div class="boxlistcontent">
<roundcube:object name="mailboxlist" id="mailboxlist" class="treelist" maxlength="25" /> <roundcube:object name="mailboxlist" id="mailboxlist" class="treelist" folder_filter="mail" />
</div> </div>
<div class="boxfooter"></div> <div class="boxfooter"></div>
</div> </div>
</div> </div>
<roundcube:else />
<roundcube:object name="mailboxlist" folder_filter="mail" type="js" />
<roundcube:endif /> <roundcube:endif />
<div id="messageframe"> <div id="messageframe">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 36 KiB

@ -39,6 +39,8 @@
<li><roundcube:button command="download" label="emlsave" class="icon" classAct="icon active" innerclass="icon download" /></li> <li><roundcube:button command="download" label="emlsave" class="icon" classAct="icon active" innerclass="icon download" /></li>
<li><roundcube:button command="edit" prop="new" label="editasnew" class="icon" classAct="icon active" innerclass="icon edit" /></li> <li><roundcube:button command="edit" prop="new" label="editasnew" class="icon" classAct="icon active" innerclass="icon edit" /></li>
<li><roundcube:button command="viewsource" label="viewsource" class="icon" classAct="icon active" innerclass="icon viewsource" /></li> <li><roundcube:button command="viewsource" label="viewsource" class="icon" classAct="icon active" innerclass="icon viewsource" /></li>
<li><roundcube:button command="move" label="moveto" class="icon" classAct="icon active" innerclass="icon move folder-selector-link" /></li>
<li><roundcube:button command="copy" label="copyto" class="icon" classAct="icon active" innerclass="icon copy folder-selector-link" /></li>
<li><roundcube:button command="open" label="openinextwin" target="_blank" class="icon" classAct="icon active" innerclass="icon extwin" /></li> <li><roundcube:button command="open" label="openinextwin" target="_blank" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
<roundcube:container name="messagemenu" id="messagemenu" /> <roundcube:container name="messagemenu" id="messagemenu" />
</ul> </ul>

@ -417,12 +417,6 @@ a.iconbutton.threadmode.selected {
right: 0; right: 0;
} }
#messagetoolbar .toolbarselect {
position: absolute;
bottom: 6px;
right: 3px;
}
#messagesearchtools { #messagesearchtools {
position: absolute; position: absolute;
right: 0; right: 0;

@ -2329,6 +2329,38 @@ ul.toolbarmenu li span.conversation {
z-index: 255; z-index: 255;
} }
/*** folder selector ***/
#folder-selector li a span {
background: url("images/listicons.png") 4px -2021px no-repeat;
display: block;
height: 17px;
min-height: 14px;
padding: 4px 4px 1px 28px;
overflow: hidden;
max-width: 120px;
text-overflow: ellipsis;
}
#folder-selector li a.virtual {
opacity: .2;
}
#folder-selector li a.inbox span {
background-position: 4px -2049px;
}
#folder-selector li a.drafts span {
background-position: 4px -1388px;
}
#folder-selector li a.sent span {
background-position: 4px -2074px;
}
#folder-selector li a.trash span {
background-position: 4px -1508px;
}
#folder-selector li a.junk span {
background-position: 4px -2100px;
}
/*** attachment list ***/ /*** attachment list ***/

@ -16,9 +16,6 @@
<roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" /> <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
<roundcube:endif /> <roundcube:endif />
<roundcube:include file="/includes/mailtoolbar.html" /> <roundcube:include file="/includes/mailtoolbar.html" />
<div class="toolbarselect">
<roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('move', this.options[this.selectedIndex].value)" class="mailboxlist decorated" folder_filter="mail" />
</div>
</div> </div>
<roundcube:if condition="!env:extwin" /> <roundcube:if condition="!env:extwin" />
@ -36,6 +33,7 @@
<div id="mailview-right" class="offset uibox"> <div id="mailview-right" class="offset uibox">
<roundcube:else /> <roundcube:else />
<roundcube:object name="mailboxlist" folder_filter="mail" type="js" />
<div id="mailview-right" class="offset fullwidth uibox"> <div id="mailview-right" class="offset fullwidth uibox">
<roundcube:endif /> <roundcube:endif />

@ -369,8 +369,10 @@ function rcube_mail_ui()
function body_mouseup(e) function body_mouseup(e)
{ {
var config, obj, target = e.target; var config, obj, target = e.target;
if (target.className == 'inner') if (target.className == 'inner')
target = e.target.parentNode; target = e.target.parentNode;
for (var id in popups) { for (var id in popups) {
obj = popups[id]; obj = popups[id];
config = popupconfig[id]; config = popupconfig[id];
@ -379,9 +381,10 @@ function rcube_mail_ui()
&& !config.toggle && !config.toggle
&& (!config.editable || !target_overlaps(target, obj.get(0))) && (!config.editable || !target_overlaps(target, obj.get(0)))
&& (!config.sticky || !rcube_mouse_is_over(e, obj.get(0))) && (!config.sticky || !rcube_mouse_is_over(e, obj.get(0)))
&& !$(target).is('.folder-selector-link')
) { ) {
var myid = id+''; var myid = id+'';
window.setTimeout(function(){ show_popupmenu(myid, false) }, 10); window.setTimeout(function() { show_popupmenu(myid, false); }, 10);
} }
} }
} }

Loading…
Cancel
Save