From 44c2639cbeb9bf612d178515c4db2bff0235a38d Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Mon, 13 Oct 2014 15:33:39 +0200 Subject: [PATCH] Save email message a task is created from as relation (#3439); display the reference in the task details and edit dialogs --- .../drivers/kolab/tasklist_kolab_driver.php | 72 +++++++++++++++++- plugins/tasklist/drivers/tasklist_driver.php | 14 ++++ plugins/tasklist/localization/en_US.inc | 2 + plugins/tasklist/skins/larry/sprites.png | Bin 3229 -> 5523 bytes plugins/tasklist/skins/larry/tasklist.css | 50 ++++++++++++ .../skins/larry/templates/mainview.html | 4 + .../skins/larry/templates/taskedit.html | 5 ++ plugins/tasklist/tasklist.js | 68 +++++++++++++++++ plugins/tasklist/tasklist.php | 61 ++++++++++++++- 9 files changed, 272 insertions(+), 4 deletions(-) diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php index 817cfdf9..e44b2c6a 100644 --- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php +++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php @@ -819,6 +819,59 @@ class tasklist_kolab_driver extends tasklist_driver $config->save_tags($uid, $tags); } + /** + * Find messages linked with a task record + */ + private function get_links($uid) + { + $config = kolab_storage_config::get_instance(); + return array_map(array($this, '_convert_message_uri'), $config->get_object_links($uid)); + } + + /** + * + */ + private function save_links($uid, $links) + { + // make sure we have a valid array + if (empty($links)) { + $links = array(); + } + + // convert the given (simplified) message links into absolute IMAP URIs + $links = array_map(function($link) { + $url = parse_url(substr($link, 8)); + parse_str($url['query'], $linkref); + + $path = explode('/', $url['path']); + $linkref['uid'] = array_pop($path); + $linkref['folder'] = join('/', array_map('rawurldecode', $path)); + + return kolab_storage_config::build_member_url($linkref); + }, $links); + + $config = kolab_storage_config::get_instance(); + $remove = array_diff($config->get_object_links($uid), $links); + return $config->save_object_links($uid, $links, $remove); + } + + /** + * Simplify the given message URI by converting the mailbox + * part into a relative IMAP path valid for the current user. + */ + protected function _convert_message_uri($uri) + { + if (strpos($uri, 'imap:///') === 0) { + $linkref = kolab_storage_config::parse_member_url($uri); + + return 'imap:///' . implode('/', array_map('rawurlencode', explode('/', $linkref['folder']))) . + '/' . $linkref['uid'] . + '?' . http_build_query($linkref['params'], '', '&'); + } + + return $uri; + } + /** * Convert from Kolab_Format to internal representation */ @@ -839,6 +892,7 @@ class tasklist_kolab_driver extends tasklist_driver 'organizer' => $record['organizer'], 'sequence' => $record['sequence'], 'tags' => $record['tags'], + 'links' => $this->get_links($record['uid']), ); // convert from DateTime to internal date format @@ -1013,9 +1067,10 @@ class tasklist_kolab_driver extends tasklist_driver if (!$list_id || !($folder = $this->get_folder($list_id))) return false; - // tags are stored separately + // email links and tags are stored separately + $links = $task['links']; $tags = $task['tags']; - unset($task['tags']); + unset($task['tags'], $task['links']); // moved from another folder if ($task['_fromlist'] && ($fromfolder = $this->get_folder($task['_fromlist']))) { @@ -1049,6 +1104,8 @@ class tasklist_kolab_driver extends tasklist_driver $saved = false; } else { + // save links in configuration.relation object + $this->save_links($object['uid'], $links); // save tags in configuration.relation object $this->save_tags($object['uid'], $tags); @@ -1169,6 +1226,17 @@ class tasklist_kolab_driver extends tasklist_driver return false; } + /** + * Build a URI representing the given message reference + * + * @see tasklist_driver::get_message_uri() + */ + public function get_message_uri($headers, $folder) + { + $uri = kolab_storage_config::get_message_uri($headers, $folder); + return $this->_convert_message_uri($uri); + } + /** * */ diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php index cdaa76ba..2102d219 100644 --- a/plugins/tasklist/drivers/tasklist_driver.php +++ b/plugins/tasklist/drivers/tasklist_driver.php @@ -287,6 +287,20 @@ abstract class tasklist_driver */ public function get_attachment_body($id, $task) { } + /** + * Build a URI representing the given message reference + * + * @param object rcube_message_header Instance holding the message headers + * @param string IMAP folder the message resides in + * + * @return string An URI referencing the given IMAP message + */ + public function get_message_uri($headers, $folder) + { + // to be implemented by the derived classes + return false; + } + /** * Helper method to determine whether the given task is considered "complete" * diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc index 72759959..4563999b 100644 --- a/plugins/tasklist/localization/en_US.inc +++ b/plugins/tasklist/localization/en_US.inc @@ -37,6 +37,7 @@ $labels['start'] = 'Start'; $labels['starttime'] = 'Start time'; $labels['alarms'] = 'Reminder'; $labels['repeat'] = 'Repeat'; +$labels['links'] = 'References'; $labels['status'] = 'Status'; $labels['status-needs-action'] = 'Needs action'; $labels['status-in-process'] = 'In process'; @@ -61,6 +62,7 @@ $labels['mytasks'] = 'My tasks'; $labels['mytaskstitle'] = 'Tasks assigned to you'; $labels['nodate'] = 'no date'; $labels['removetag'] = 'Remove'; +$labels['removelink'] = 'Remove email reference'; $labels['auto'] = 'Auto'; $labels['taskdetails'] = 'Details'; diff --git a/plugins/tasklist/skins/larry/sprites.png b/plugins/tasklist/skins/larry/sprites.png index 7a9c89f422bfb9ab643a351fbb3e3f238e746173..3552b0087baeca177c734ebdf7d460e57eb88821 100644 GIT binary patch literal 5523 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 literal 3229 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 +
diff --git a/plugins/tasklist/skins/larry/templates/taskedit.html b/plugins/tasklist/skins/larry/templates/taskedit.html index e44c5d8a..81556681 100644 --- a/plugins/tasklist/skins/larry/templates/taskedit.html +++ b/plugins/tasklist/skins/larry/templates/taskedit.html @@ -54,6 +54,11 @@
+
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js index 8a928874..3cadd57a 100644 --- a/plugins/tasklist/tasklist.js +++ b/plugins/tasklist/tasklist.js @@ -558,6 +558,12 @@ function rcube_tasklist_ui(settings) } }); + // register click handler for message links + $('#task-links, #taskedit-links').on('click', 'li a.messagelink', function(e) { + rcmail.open_window(this.href); + return false; + }); + // handle global document clicks: close popup menus $(document.body).click(clear_popups); @@ -1778,6 +1784,13 @@ function rcube_tasklist_ui(settings) } } + // build attachments list + $('#task-links').hide(); + if ($.isArray(rec.links) && rec.links.length) { + task_show_links(rec.links || [], $('#task-links').children('.task-text')); + $('#task-links').show(); + } + // list task attendees if (list.attendees && rec.attendees) { /* @@ -1984,6 +1997,14 @@ function rcube_tasklist_ui(settings) // set alarm(s) me.set_alarms_edit('#taskedit-alarms', action != 'new' && rec.valarms ? rec.valarms : []); + if ($.isArray(rec.links) && rec.links.length) { + task_show_links(rec.links, $('#taskedit-links .task-text'), true); + $('#taskedit-links').show(); + } + else { + $('#taskedit-links').hide(); + } + // set recurrence me.set_recurrence_edit(rec); @@ -2268,6 +2289,53 @@ function rcube_tasklist_ui(settings) delete rcmail.env.attachments[id]; } + /** + * + */ + function task_show_links(links, container, edit) + { + var dellink, ul = $('