summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--program/js/app.js36
-rw-r--r--program/js/treelist.js7
-rw-r--r--program/localization/en_US/labels.inc3
-rw-r--r--program/steps/settings/folders.inc49
-rw-r--r--skins/classic/functions.js5
-rw-r--r--skins/classic/settings.css5
-rw-r--r--skins/classic/templates/folders.html1
-rw-r--r--skins/larry/settings.css5
-rw-r--r--skins/larry/styles.css1
-rw-r--r--skins/larry/templates/folders.html1
-rw-r--r--skins/larry/ui.js5
12 files changed, 109 insertions, 10 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 5148767d4..0fe3cec3f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Added namespace filter in Folder Manager
- Added folder searching in Folder Manager
- Added config option 'imap_log_session' to enable Roundcube <-> IMAP session ID logging
- Added config option 'log_session_id' to control the lengh of the session identifer in logs
diff --git a/program/js/app.js b/program/js/app.js
index c64318858..5a8734772 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -5862,8 +5862,9 @@ function rcube_webmail()
row.attr({id: 'rcmli' + this.html_identifier_encode(id), 'class': class_name});
if (!refrow || !refrow.length) {
- // remove old subfolders and toggle
+ // remove old data, subfolders and toggle
$('ul,div.treetoggle', row).remove();
+ row.removeData('filtered');
}
// set folder name
@@ -5990,7 +5991,7 @@ function rcube_webmail()
this.subscription_list.expand(this.folder_id2name(parent.id));
}
- row = row.get(0);
+ row = row.show().get(0);
if (row.scrollIntoView)
row.scrollIntoView();
@@ -6134,6 +6135,37 @@ function rcube_webmail()
$('#folder-size').replaceWith(size);
};
+ // filter folders by namespace
+ this.folder_filter = function(prefix)
+ {
+ this.subscription_list.reset_search();
+
+ this.subscription_list.container.children('li').each(function() {
+ var i, folder = ref.folder_id2name(this.id);
+ // show all folders
+ if (prefix == '---') {
+ }
+ // got namespace prefix
+ else if (prefix) {
+ if (folder !== prefix) {
+ $(this).data('filtered', true).hide();
+ return
+ }
+ }
+ // no namespace prefix, filter out all other namespaces
+ else {
+ // first get all namespace roots
+ for (i in ref.env.ns_roots) {
+ if (folder === ref.env.ns_roots[i]) {
+ $(this).data('filtered', true).hide();
+ return;
+ }
+ }
+ }
+
+ $(this).removeData('filtered').show();
+ });
+ };
/*********************************************************/
/********* GUI functionality *********/
diff --git a/program/js/treelist.js b/program/js/treelist.js
index cc1880da2..5e6d326fc 100644
--- a/program/js/treelist.js
+++ b/program/js/treelist.js
@@ -522,6 +522,11 @@ function rcube_treelist_widget(node, p)
var li, sli;
if (!node.virtual && !node.deleted && String(node.text).toLowerCase().indexOf(q) >= 0 && hits.indexOf(node.id) < 0) {
li = id2dom(node.id);
+
+ // skip already filtered nodes
+ if (li.data('filtered'))
+ return;
+
sli = $('<li>')
.attr('id', li.attr('id') + '--xsR')
.attr('class', li.attr('class'))
@@ -566,7 +571,7 @@ function rcube_treelist_widget(node, p)
searchfield.val('');
$(container).children('li.searchresult__').remove();
- $(container).children('li').show();
+ $(container).children('li').filter(function() { return !$(this).data('filtered'); }).show();
search_active = false;
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index e3fe76b2b..449b278f8 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -549,6 +549,9 @@ $labels['personalfolder'] = 'Private Folder';
$labels['otherfolder'] = 'Other User\'s Folder';
$labels['sharedfolder'] = 'Public Folder';
$labels['findfolders'] = 'Find folders';
+$labels['namespace.personal'] = 'Personal';
+$labels['namespace.other'] = 'Other users';
+$labels['namespace.shared'] = 'Shared';
$labels['sortby'] = 'Sort by';
$labels['sortasc'] = 'Sort ascending';
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 061cd8893..14e41d607 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -181,8 +181,9 @@ $OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting'
// register UI objects
$OUTPUT->add_handlers(array(
- 'foldersubscription' => 'rcube_subscription_form',
+ 'foldersubscription' => 'rcmail_subscription_form',
'folderframe' => 'rcmail_folder_frame',
+ 'folderfilter' => 'rcmail_folder_filter',
'quotadisplay' => array($RCMAIL, 'quota_display'),
));
@@ -190,7 +191,7 @@ $OUTPUT->send('folders');
// build table with all folders listed by server
-function rcube_subscription_form($attrib)
+function rcmail_subscription_form($attrib)
{
global $RCMAIL, $OUTPUT;
@@ -424,6 +425,50 @@ function rcmail_folder_frame($attrib)
return $OUTPUT->frame($attrib, true);
}
+function rcmail_folder_filter($attrib)
+{
+ global $RCMAIL;
+
+ $storage = $RCMAIL->get_storage();
+ $namespace = $storage->get_namespace();
+
+ if (empty($namespace['personal']) && empty($namespace['shared']) && empty($namespace['other'])) {
+ return '';
+ }
+
+ if (!$attrib['id']) {
+ $attrib['id'] = 'rcmfolderfilter';
+ }
+
+ $attrib['onchange'] = rcmail_output::JS_OBJECT_NAME . '.folder_filter(this.value)';
+
+ $roots = array();
+ $select = new html_select($attrib);
+ $select->add($RCMAIL->gettext('all'), '---');
+
+ foreach (array_keys($namespace) as $type) {
+ foreach ((array)$namespace[$type] as $ns) {
+ $root = rtrim($ns[0], $ns[1]);
+ $label = $RCMAIL->gettext('namespace.' . $type);
+
+ if (count($namespace[$type]) > 1) {
+ $label .= ' (' . rcube_charset::convert($root, 'UTF7-IMAP', RCUBE_CHARSET) . ')';
+ }
+
+ $select->add($label, $root);
+
+ if (strlen($root)) {
+ $roots[] = $root;
+ }
+ }
+ }
+
+ $RCMAIL->output->add_gui_object('foldersfilter', $attrib['id']);
+ $RCMAIL->output->set_env('ns_roots', $roots);
+
+ return $select->show();
+}
+
function rcmail_rename_folder($oldname, $newname)
{
global $RCMAIL;
diff --git a/skins/classic/functions.js b/skins/classic/functions.js
index f17f393c2..2bf1538c4 100644
--- a/skins/classic/functions.js
+++ b/skins/classic/functions.js
@@ -644,13 +644,14 @@ folder_search_init: function(container)
$('.boxtitle a.search', container).click(function(e) {
var title = $('.boxtitle', container),
box = $('.listsearchbox', container),
- dir = box.is(':visible') ? -1 : 1;
+ dir = box.is(':visible') ? -1 : 1,
+ height = 24 + ($('select', box).length ? 24 : 0);
box.slideToggle({
duration: 160,
progress: function(animation, progress) {
if (dir < 0) progress = 1 - progress;
- $('.boxlistcontent', container).css('top', (title.outerHeight() + 24 * progress) + 'px');
+ $('.boxlistcontent', container).css('top', (title.outerHeight() + height * progress) + 'px');
},
complete: function() {
box.toggleClass('expanded');
diff --git a/skins/classic/settings.css b/skins/classic/settings.css
index cd250d57e..9dda7bb8d 100644
--- a/skins/classic/settings.css
+++ b/skins/classic/settings.css
@@ -21,6 +21,11 @@
text-indent: 50000px;
}
+.listsearchbox select {
+ width: 100%;
+ margin: 1px 0;
+}
+
#identities-table,
#sections-table
{
diff --git a/skins/classic/templates/folders.html b/skins/classic/templates/folders.html
index 8ed0b5fdc..ac824306f 100644
--- a/skins/classic/templates/folders.html
+++ b/skins/classic/templates/folders.html
@@ -29,6 +29,7 @@
<a class="iconbutton searchicon"></a>
<roundcube:button command="reset-foldersearch" id="folderlistsearch-reset" class="iconbutton reset" title="resetsearch" width="13" height="13" />
</div>
+ <roundcube:object name="folderfilter" id="folderlist-filter" />
</div>
<div id="folderlist-content" class="boxlistcontent">
<roundcube:object name="foldersubscription" form="subscriptionform" id="subscription-table"
diff --git a/skins/larry/settings.css b/skins/larry/settings.css
index cda47b631..b2779982c 100644
--- a/skins/larry/settings.css
+++ b/skins/larry/settings.css
@@ -224,6 +224,11 @@
top: 34px;
}
+.listsearchbox select {
+ width: 100%;
+ margin: 3px 0;
+}
+
#folderslist,
#identitieslist {
position: absolute;
diff --git a/skins/larry/styles.css b/skins/larry/styles.css
index d7fd588a8..b2b4f9a05 100644
--- a/skins/larry/styles.css
+++ b/skins/larry/styles.css
@@ -1957,7 +1957,6 @@ ul.proplist li {
}
.listsearchbox {
- position: relative;
padding: 4px;
background: #c7e3ef;
display: none;
diff --git a/skins/larry/templates/folders.html b/skins/larry/templates/folders.html
index 3d016cad1..977dff451 100644
--- a/skins/larry/templates/folders.html
+++ b/skins/larry/templates/folders.html
@@ -29,6 +29,7 @@
<a class="iconbutton searchicon"></a>
<roundcube:button command="reset-foldersearch" id="folderlistsearch-reset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
</div>
+ <roundcube:object name="folderfilter" id="folderlist-filter" />
</div>
<div id="folderslist-content" class="scroller withfooter">
<roundcube:object name="foldersubscription" form="subscriptionform" id="subscription-table" class="treelist listing folderlist" />
diff --git a/skins/larry/ui.js b/skins/larry/ui.js
index 1eb8e899a..7b08aeadd 100644
--- a/skins/larry/ui.js
+++ b/skins/larry/ui.js
@@ -540,13 +540,14 @@ function rcube_mail_ui()
$('.boxtitle a.search', container).click(function(e) {
var title = $('.boxtitle', container),
box = $('.listsearchbox', container),
- dir = box.is(':visible') ? -1 : 1;
+ dir = box.is(':visible') ? -1 : 1,
+ height = 34 + ($('select', box).length ? 24 : 0);
box.slideToggle({
duration: 160,
progress: function(animation, progress) {
if (dir < 0) progress = 1 - progress;
- $('.scroller', container).css('top', (title.outerHeight() + 34 * progress) + 'px');
+ $('.scroller', container).css('top', (title.outerHeight() + height * progress) + 'px');
},
complete: function() {
box.toggleClass('expanded');