diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php index 8ad776ab..3c5ad384 100644 --- a/plugins/tasklist/drivers/database/tasklist_database_driver.php +++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php @@ -286,7 +286,7 @@ class tasklist_database_driver extends tasklist_driver if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) $sql_add .= ' AND complete=1'; - else // don't show complete tasks by default + else if (empty($filter['since'])) // don't show complete tasks by default $sql_add .= ' AND complete<1'; if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) @@ -301,6 +301,10 @@ class tasklist_database_driver extends tasklist_driver $sql_add = 'AND (' . join(' OR ', $sql_query) . ')'; } + if ($filter['since'] && is_numeric($filter['since'])) { + $sql_add .= ' AND changed >= ' . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since'])); + } + $tasks = array(); if (!empty($list_ids)) { $result = $this->rc->db->query(sprintf( diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php index 6e41fd75..18a45770 100644 --- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php +++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php @@ -372,7 +372,7 @@ class tasklist_kolab_driver extends tasklist_driver $query = array(); if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) $query[] = array('tags','~','x-complete'); - else + else if (empty($filter['since'])) $query[] = array('tags','!~','x-complete'); // full text search (only works with cache enabled) @@ -383,6 +383,10 @@ class tasklist_kolab_driver extends tasklist_driver } } + if ($filter['since']) { + $query[] = array('changed', '>=', $filter['since']); + } + foreach ($lists as $list_id) { $folder = $this->folders[$list_id]; foreach ((array)$folder->select($query) as $record) { diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js index 19db0fe9..631494c6 100644 --- a/plugins/tasklist/tasklist.js +++ b/plugins/tasklist/tasklist.js @@ -132,6 +132,7 @@ function rcube_tasklist_ui(settings) rcmail.addEventListener('plugin.destroy_tasklist', destroy_list); rcmail.addEventListener('plugin.reload_data', function(){ list_tasks(null); }); rcmail.addEventListener('plugin.unlock_saving', unlock_saving); + rcmail.addEventListener('requestrefresh', before_refresh); // start loading tasks fetch_counts(); @@ -438,6 +439,19 @@ function rcube_tasklist_ui(settings) loadstate.lists = active_lists(); } + /** + * Modify query parameters for refresh requests + */ + function before_refresh(query) + { + query.filter = filtermask == FILTER_MASK_COMPLETE ? FILTER_MASK_COMPLETE : FILTER_MASK_ALL; + query.lists = active_lists().join(','); + if (search_query) + query.q = search_query; + + return query; + } + /** * Callback if task data from server is ready */ diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php index 9d5544cd..e6b5d1cd 100644 --- a/plugins/tasklist/tasklist.php +++ b/plugins/tasklist/tasklist.php @@ -90,6 +90,7 @@ class tasklist extends rcube_plugin $this->register_action('mail2task', array($this, 'mail_message2task')); $this->register_action('get-attachment', array($this, 'attachment_get')); $this->register_action('upload', array($this, 'attachment_upload')); + $this->add_hook('refresh', array($this, 'refresh')); $this->collapsed_tasks = array_filter(explode(',', $this->rc->config->get('tasklist_collapsed_tasks', ''))); } @@ -540,8 +541,17 @@ class tasklist extends rcube_plugin } */ + $data = $this->tasks_data($this->driver->list_tasks($filter, $lists), $f, $tags); + $this->rc->output->command('plugin.data_ready', array('filter' => $f, 'lists' => $lists, 'search' => $search, 'data' => $data, 'tags' => array_values(array_unique($tags)))); + } + + /** + * Prepare and sort the given task records to be sent to the client + */ + private function tasks_data($records, $f, &$tags) + { $data = $tags = $this->task_tree = $this->task_titles = array(); - foreach ($this->driver->list_tasks($filter, $lists) as $rec) { + foreach ($records as $rec) { if ($rec['parent_id']) { $this->task_tree[$rec['id']] = $rec['parent_id']; } @@ -558,7 +568,7 @@ class tasklist extends rcube_plugin array_walk($data, array($this, 'task_walk_tree')); usort($data, array($this, 'task_sort_cmp')); - $this->rc->output->command('plugin.data_ready', array('filter' => $f, 'lists' => $lists, 'search' => $search, 'data' => $data, 'tags' => array_values(array_unique($tags)))); + return $data; } /** @@ -724,6 +734,28 @@ class tasklist extends rcube_plugin exit; } + /** + * Handler for keep-alive requests + * This will check for updated data in active lists and sync them to the client + */ + public function refresh($attr) + { + $filter = array( + 'since' => $attr['last'], + 'search' => get_input_value('q', RCUBE_INPUT_GPC), + 'mask' => intval(get_input_value('filter', RCUBE_INPUT_GPC)) & self::FILTER_MASK_COMPLETE, + ); + $lists = get_input_value('lists', RCUBE_INPUT_GPC);; + + $updates = $this->driver->list_tasks($filter, $lists); + if (!empty($updates)) { + $this->rc->output->command('plugin.refresh_task', $this->tasks_data($updates, 255, $tags)); + + // update counts + $counts = $this->driver->count_tasks($lists); + $this->rc->output->command('plugin.update_counts', $counts); + } + } /** * Handler for pending_alarms plugin hook triggered by the calendar module on keep-alive requests.