From e688bd44f7fb3b92413ae64735e29c75d7380ac2 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Thu, 24 Oct 2013 16:29:33 +0200 Subject: [PATCH] Add 'focusview' mode to quickly reduce the view to tasks from the selected list only (#2380) --- plugins/tasklist/localization/en_US.inc | 1 + plugins/tasklist/skins/larry/sprites.png | Bin 3741 -> 4577 bytes plugins/tasklist/skins/larry/tasklist.css | 30 +++++++++-- plugins/tasklist/tasklist.js | 62 +++++++++++++++++++--- plugins/tasklist/tasklist.php | 4 +- plugins/tasklist/tasklist_ui.php | 2 +- 6 files changed, 85 insertions(+), 14 deletions(-) diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc index 57d6c3c4..a1d381b7 100644 --- a/plugins/tasklist/localization/en_US.inc +++ b/plugins/tasklist/localization/en_US.inc @@ -51,6 +51,7 @@ $labels['listactions'] = 'List options...'; $labels['listname'] = 'Name'; $labels['showalarms'] = 'Show alarms'; $labels['import'] = 'Import'; +$labels['focusview'] = 'View only this list'; // date words $labels['on'] = 'on'; diff --git a/plugins/tasklist/skins/larry/sprites.png b/plugins/tasklist/skins/larry/sprites.png index b20b2db08e723fa8693e1bd01ee42fd4e415adf8..5c6b9fdec3166a19d8b5fc2ebbbea9a06efb3b3d 100644 GIT binary patch literal 4577 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 Hu0mjft_dS$ diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css index 9efc18b8..ab74a1f2 100644 --- a/plugins/tasklist/skins/larry/tasklist.css +++ b/plugins/tasklist/skins/larry/tasklist.css @@ -218,7 +218,7 @@ body.attachmentwin #topnav .topright { #tasklists li { margin: 0; height: 20px; - padding: 6px 8px 2px; + padding: 6px 8px 2px 6px; display: block; position: relative; white-space: nowrap; @@ -235,10 +235,13 @@ body.attachmentwin #topnav .topright { #tasklists li span.listname { display: block; + position: absolute; + top: 7px; + left: 26px; + right: 26px; cursor: default; padding-bottom: 2px; padding-right: 30px; - margin-right: 20px; color: #004458; overflow: hidden; text-overflow: ellipsis; @@ -247,7 +250,21 @@ body.attachmentwin #topnav .topright { } #tasklists li span.handle { - display: none; + display: inline-block; + width: 16px; + height: 16px; + margin-right: 4px; + background: url(sprites.png) -200px 0 no-repeat; + cursor: pointer; +} + +#tasklists li span.handle:hover { + background-position: -20px -101px; +} + +#tasklists li.focusview span.handle, +#tasklists li.focusview span.handle:hover { + background-position: -2px -101px; } #tasklists li.selected span.listname { @@ -278,6 +295,11 @@ body.attachmentwin #topnav .topright { color: #aaa; } +#tasklists li.virtual span.handle { + background: none; + cursor: default; +} + #tasklists li input { position: absolute; top: 5px; @@ -610,7 +632,7 @@ ul.toolbarmenu li span.collapse { } ul.toolbarmenu li span.add { - background-position: 0 -100px; + background-position: 0 -302px; } ul.toolbarmenu li span.expand { diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js index 68ea1174..0293d8f8 100644 --- a/plugins/tasklist/tasklist.js +++ b/plugins/tasklist/tasklist.js @@ -54,6 +54,7 @@ function rcube_tasklist_ui(settings) var filtermask = FILTER_MASK_ALL; var loadstate = { filter:-1, lists:'', search:null }; var idcount = 0; + var focusview; var saving_lock; var ui_loading; var taskcounts = {}; @@ -128,7 +129,8 @@ function rcube_tasklist_ui(settings) // register server callbacks rcmail.addEventListener('plugin.data_ready', data_ready); - rcmail.addEventListener('plugin.refresh_task', update_taskitem); + rcmail.addEventListener('plugin.update_task', update_taskitem); + rcmail.addEventListener('plugin.refresh_tasks', function(p) { update_taskitem(p, true); }); rcmail.addEventListener('plugin.update_counts', update_counts); rcmail.addEventListener('plugin.insert_tasklist', insert_list); rcmail.addEventListener('plugin.update_tasklist', update_list); @@ -686,11 +688,11 @@ function rcube_tasklist_ui(settings) /** * Callback from server to update a single task item */ - function update_taskitem(rec) + function update_taskitem(rec, filter) { // handle a list of task records if ($.isArray(rec)) { - $.each(rec, function(i,r){ update_taskitem(r); }); + $.each(rec, function(i,r){ update_taskitem(r, filter); }); return; } @@ -730,10 +732,13 @@ function rcube_tasklist_ui(settings) } } - if (list.active) - render_task(rec, oldid); - else + if (list.active) { + if (!filter || match_filter(rec, {})) + render_task(rec, oldid); + } + else { $('li[rel="'+id+'"]', rcmail.gui_objects.resultlist).remove(); + } append_tags(rec.tags || []); fix_tree_toggles(); @@ -1525,7 +1530,11 @@ function rcube_tasklist_ui(settings) return cache[rec.id]; } - var match = !filtermask || (filtermask & rec.mask) > 0 + var match = !filtermask || (filtermask & rec.mask) > 0; + + // in focusview mode, only tasks from the selected list are allowed + if (focusview && rec.list != focusview) + match = false; if (match && tagsfilter.length) { match = rec.tags && rec.tags.length; @@ -1847,6 +1856,11 @@ function rcube_tasklist_ui(settings) if (!this.checked) remove_tasks(id); else list_tasks(null); rcmail.http_post('tasklist', { action:'subscribe', l:{ id:id, active:me.tasklists[id].active?1:0 } }); + + // disable focusview + if (!this.checked && focusview == id) { + set_focusview(null); + } } }).data('id', id).get(0).checked = me.tasklists[id].active || false; @@ -1855,6 +1869,15 @@ function rcube_tasklist_ui(settings) rcmail.select_folder(id, 'rcmlitasklist'); rcmail.enable_command('list-edit', 'list-remove', 'list-import', me.tasklists[id].editable); me.selected_list = id; + + // click on handle icon toggles focusview + if (e.target.className == 'handle') { + set_focusview(focusview == id ? null : id) + } + // disable focusview when selecting another list + else if (focusview && id != focusview) { + set_focusview(null); + } }) .dblclick(function(e){ list_edit_dialog($(this).data('id')); @@ -1864,6 +1887,31 @@ function rcube_tasklist_ui(settings) .addClass(me.tasklists[id].editable ? null : 'readonly'); } + /** + * Enable/disable focusview mode for the given list + */ + function set_focusview(id) + { + if (focusview && focusview != id) + $(rcmail.get_folder_li(focusview, 'rcmlitasklist')).removeClass('focusview'); + + focusview = id; + + // activate list if necessary + if (focusview && !me.tasklists[id].active) { + $('input', rcmail.get_folder_li(id, 'rcmlitasklist')).get(0).checked = true; + me.tasklists[id].active = true; + fetch_counts(); + } + + // update list + list_tasks(null); + + if (focusview) { + $(rcmail.get_folder_li(focusview, 'rcmlitasklist')).addClass('focusview'); + } + } + // init dialog by default init_taskedit(); diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php index 68d82c4f..aaeea95b 100644 --- a/plugins/tasklist/tasklist.php +++ b/plugins/tasklist/tasklist.php @@ -281,7 +281,7 @@ class tasklist extends rcube_plugin foreach ($refresh as $i => $r) $this->encode_task($refresh[$i]); } - $this->rc->output->command('plugin.refresh_task', $refresh); + $this->rc->output->command('plugin.update_task', $refresh); } } @@ -751,7 +751,7 @@ class tasklist extends rcube_plugin $updates = $this->driver->list_tasks($filter, $lists); if (!empty($updates)) { - $this->rc->output->command('plugin.refresh_task', $this->tasks_data($updates, 255, $tags)); + $this->rc->output->command('plugin.refresh_tasks', $this->tasks_data($updates, 255, $tags), true); // update counts $counts = $this->driver->count_tasks($lists); diff --git a/plugins/tasklist/tasklist_ui.php b/plugins/tasklist/tasklist_ui.php index dab9b127..21faba3e 100644 --- a/plugins/tasklist/tasklist_ui.php +++ b/plugins/tasklist/tasklist_ui.php @@ -117,7 +117,7 @@ class tasklist_ui $li .= html::tag('li', array('id' => 'rcmlitasklist' . $html_id, 'class' => $class), ($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_list[]', 'value' => $id, 'checked' => $prop['active']))) . - html::span('handle', ' ') . + html::span(array('class' => 'handle', 'title' => $this->plugin->gettext('focusview')), ' ') . html::span(array('class' => 'listname', 'title' => $title), $prop['listname'])); }