plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Mon Oct 13 18:42:32 CEST 2014
plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php | 19 ++++
plugins/tasklist/drivers/tasklist_driver.php | 18 +++-
plugins/tasklist/skins/larry/buttons.png |binary
plugins/tasklist/skins/larry/tasklist.css | 40 ++++++++
plugins/tasklist/tasklist.js | 21 ++++
plugins/tasklist/tasklist.php | 67 ++++++++++++++-
plugins/tasklist/tasklist_base.js | 28 ++++++
plugins/tasklist/tasklist_ui.php | 17 +++
8 files changed, 204 insertions(+), 6 deletions(-)
New commits:
commit adc41ebf61bdac6c59beb9796a6881beaad9392c
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 18:40:39 2014 +0200
- List linked tasks in mail view, like notes
- Deep-links into the tasks view opening the linked task
- Mark tasks as complete directly from mail view
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index e44b2c6..3ee1100 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -1238,6 +1238,25 @@ class tasklist_kolab_driver extends tasklist_driver
}
/**
+ * Find tasks assigned to a specified message
+ *
+ * @see tasklist_driver::get_message_related_tasks()
+ */
+ public function get_message_related_tasks($headers, $folder)
+ {
+ $config = kolab_storage_config::get_instance();
+ $result = $config->get_message_relations($headers, $folder, 'task');
+
+ foreach ($result as $idx => $rec) {
+ $task = $this->_to_rcube_task($rec);
+ $task['list'] = kolab_storage::folder_id($rec['_mailbox']);
+ $result[$idx] = $task;
+ }
+
+ return $result;
+ }
+
+ /**
*
*/
public function tasklist_edit_form($action, $list, $fieldprop)
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index 2102d21..791d2ab 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -290,8 +290,8 @@ abstract class tasklist_driver
/**
* 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
+ * @param object $headers rcube_message_header instance holding the message headers
+ * @param string $folder IMAP folder the message resides in
*
* @return string An URI referencing the given IMAP message
*/
@@ -302,6 +302,20 @@ abstract class tasklist_driver
}
/**
+ * Find tasks assigned to a specified message
+ *
+ * @param object $message rcube_message_header instance
+ * @param string $folder IMAP folder the message resides in
+ *
+ * @param array List of linked task objects
+ */
+ public function get_message_related_tasks($headers, $folder)
+ {
+ // to be implemented by the derived classes
+ return array();
+ }
+
+ /**
* Helper method to determine whether the given task is considered "complete"
*
* @param array $task Hash array with event properties:
diff --git a/plugins/tasklist/skins/larry/buttons.png b/plugins/tasklist/skins/larry/buttons.png
index 62baed6..7f1a2b6 100644
Binary files a/plugins/tasklist/skins/larry/buttons.png and b/plugins/tasklist/skins/larry/buttons.png differ
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index bf53e6b..832197d 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -1337,6 +1337,46 @@ div.tasklist-invitebox .rsvp-status.accepted,
background-position: 2px -220px;
}
+div.messagetasklinks {
+ margin: 8px 8px;
+ padding: 4px 8px;
+ border: 1px solid #dfdfdf;
+ background: #fafafa;
+ border-radius: 4px;
+}
+
+div.messagetasklinks span.messagetaskref {
+ position: relative;
+ display: inline-block;
+ margin-right: 1em;
+ padding-right: 24px;
+}
+
+div.messagetasklinks a.messagetasklink {
+ position: relative;
+ display: inline-block;
+ color: #333;
+ font-weight: bold;
+ padding: 3px 0 2px 22px;
+ text-shadow: 0px 1px 1px #fff;
+ text-decoration: none;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 16em;
+ background: url(buttons.png) -6px -115px no-repeat;
+}
+
+div.messagetasklinks span.messagetaskref.complete a.messagetasklink {
+ text-decoration: line-through;
+}
+
+div.messagetasklinks span.messagetaskref input.complete {
+ position: absolute;
+ top: 1px;
+ right: 2px;
+}
+
/** Special hacks for IE7 **/
/** They need to be in this file to also affect the task-create dialog embedded in mail view **/
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index 3cadd57..5ec467d 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -137,6 +137,11 @@ function rcube_tasklist_ui(settings)
{
// initialize task list selectors
for (var id in me.tasklists) {
+ if (settings.selected_list && me.tasklists[settings.selected_list] && !me.tasklists[settings.selected_list].active) {
+ me.tasklists[settings.selected_list].active = true;
+ me.selected_list = settings.selected_list;
+ $(rcmail.gui_objects.tasklistslist).find("input[value='"+settings.selected_list+"']").prop('checked', true);
+ }
if (me.tasklists[id].editable && (!me.selected_list || me.tasklists[id].default || (me.tasklists[id].active && !me.tasklists[me.selected_list].active))) {
me.selected_list = id;
}
@@ -269,10 +274,9 @@ function rcube_tasklist_ui(settings)
$('#taskviewsortmenu .by-' + (settings.sort_col || 'auto')).attr('aria-checked', 'true').addClass('selected');
$('#taskviewsortmenu .sortorder.' + (settings.sort_order || 'asc')).attr('aria-checked', 'true').addClass('selected');
-
// start loading tasks
fetch_counts();
- list_tasks();
+ list_tasks(settings.selected_filter);
// register event handlers for UI elements
$('#taskselector a').click(function(e) {
@@ -769,6 +773,19 @@ function rcube_tasklist_ui(settings)
append_tags(response.tags || []);
render_tasklist();
+ // show selected task dialog
+ if (settings.selected_id) {
+ if (listdata[settings.selected_id]) {
+ task_show_dialog(settings.selected_id);
+ delete settings.selected_id;
+ }
+
+ // remove _id from window location
+ if (window.history.replaceState) {
+ window.history.replaceState({}, document.title, rcmail.url('', { _list: me.selected_list }));
+ }
+ }
+
rcmail.set_busy(false, 'loading', ui_loading);
}
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 9acded6..82b3634 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -61,6 +61,7 @@ class tasklist extends rcube_plugin
public $home; // declare public to be used in other classes
private $collapsed_tasks = array();
+ private $message_tasks = array();
private $itip;
private $ical;
@@ -125,6 +126,9 @@ class tasklist extends rcube_plugin
}
else if ($args['task'] == 'mail') {
if ($args['action'] == 'show' || $args['action'] == 'preview') {
+ if ($this->rc->config->get('tasklist_mail_embed', true)) {
+ $this->add_hook('message_load', array($this, 'mail_message_load'));
+ }
$this->add_hook('template_object_messagebody', array($this, 'mail_messagebody_html'));
}
@@ -204,7 +208,8 @@ class tasklist extends rcube_plugin
$success = $refresh = false;
// force notify if hidden + active
- if ((int)$this->rc->config->get('calendar_itip_send_option', 3) === 1 && empty($rec['_reportpartstat']))
+ $itip_send_option = (int)$this->rc->config->get('calendar_itip_send_option', 3);
+ if ($itip_send_option === 1 && empty($rec['_reportpartstat']))
$rec['_notify'] = 1;
switch ($action) {
@@ -220,6 +225,24 @@ class tasklist extends rcube_plugin
}
break;
+ case 'complete':
+ $complete = intval(rcube_utils::get_input_value('complete', rcube_utils::INPUT_POST));
+ if (!($rec = $this->driver->get_task($rec))) {
+ break;
+ }
+
+ $rec['status'] = $complete ? 'COMPLETED' : ($rec['complete'] > 0 ? 'IN-PROCESS' : 'NEEDS-ACTION');
+
+ // sent itip notifications if enabled (no user interaction here)
+ if (($itip_send_option & 1)) {
+ if ($this->is_attendee($rec)) {
+ $rec['_reportpartstat'] = $rec['status'];
+ }
+ else if ($this->is_organizer($rec)) {
+ $rec['_notify'] = 1;
+ }
+ }
+
case 'edit':
$rec = $this->prepare_task($rec);
$clone = $this->handle_recurrence($rec, $this->driver->get_task($rec));
@@ -1437,7 +1460,36 @@ class tasklist extends rcube_plugin
}
}
- // prepend event boxes to message body
+ // list linked tasks
+ $links = array();
+ foreach ($this->message_tasks as $task) {
+ $checkbox = new html_checkbox(array(
+ 'name' => 'completed',
+ 'class' => 'complete',
+ 'title' => $this->gettext('complete'),
+ 'data-list' => $task['list'],
+ ));
+ $complete = $this->driver->is_complete($task);
+ $links[] = html::span('messagetaskref' . ($complete ? ' complete' : ''),
+ $checkbox->show($complete ? $task['uid'] : null, array('value' => $task['uid'])) . ' ' .
+ html::a(array(
+ 'href' => $this->rc->url(array(
+ 'task' => 'tasks',
+ 'list' => $task['list'],
+ 'id' => $task['uid'],
+ 'complete' => $complete?1:null,
+ )),
+ 'class' => 'messagetasklink',
+ 'rel' => $task['uid'] . '@' . $task['list'],
+ 'target' => '_blank',
+ ), Q($task['title']))
+ );
+ }
+ if (count($links)) {
+ $html .= html::div('messagetasklinks', join("\n", $links));
+ }
+
+ // prepend iTip/relation boxes to message body
if ($html) {
$this->load_ui();
$this->ui->init();
@@ -1466,6 +1518,17 @@ class tasklist extends rcube_plugin
}
/**
+ * Lookup backend storage and find notes associated with the given message
+ */
+ public function mail_message_load($p)
+ {
+ if (!$p['object']->headers->others['x-kolab-type']) {
+ $this->load_driver();
+ $this->message_tasks = $this->driver->get_message_related_tasks($p['object']->headers, $p['object']->folder);
+ }
+ }
+
+ /**
* Load iCalendar functions
*/
public function get_ical()
diff --git a/plugins/tasklist/tasklist_base.js b/plugins/tasklist/tasklist_base.js
index e399c53..b5ea06e 100644
--- a/plugins/tasklist/tasklist_base.js
+++ b/plugins/tasklist/tasklist_base.js
@@ -30,6 +30,7 @@ function rcube_tasklist(settings)
/* private vars */
var ui_loaded = false;
var me = this;
+ var mywin = window;
/* public members */
this.ui;
@@ -79,6 +80,18 @@ function rcube_tasklist(settings)
function mail2task_dialog(prop)
{
this.ui.edit_task(null, 'new', prop);
+ rcmail.addEventListener('responseaftertask', refresh_mailview);
+ }
+
+ /**
+ * Reload the mail view/preview to update the tasks listing
+ */
+ function refresh_mailview(e)
+ {
+ var win = rcmail.env.contentframe ? rcmail.get_frame_window(rcmail.env.contentframe) : mywin;
+ if (win && e.response.action == 'task') {
+ win.location.reload();
+ }
}
// handler for attachment-save-tasklist commands
@@ -95,6 +108,21 @@ function rcube_tasklist(settings)
}
}
+ // register event handlers on linked task items in message view
+ // the checkbox allows to mark a task as complete
+ if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
+ $('div.messagetasklinks input.complete').click(function(e) {
+ var $this = $(this);
+ $(this).closest('.messagetaskref').toggleClass('complete');
+
+ // submit change to server
+ rcmail.http_post('tasks/task', {
+ action: 'complete',
+ t: { id:this.value, list:$this.attr('data-list') },
+ complete: this.checked?1:0
+ }, rcmail.set_busy(true, 'tasklist.savingdata'));
+ });
+ }
}
/* tasklist plugin initialization (for email task) */
diff --git a/plugins/tasklist/tasklist_ui.php b/plugins/tasklist/tasklist_ui.php
index b7bb4d4..5451e2c 100644
--- a/plugins/tasklist/tasklist_ui.php
+++ b/plugins/tasklist/tasklist_ui.php
@@ -92,6 +92,23 @@ class tasklist_ui
'emails' => ';' . strtolower(join(';', $identity['emails']))
);
+ if ($list = rcube_utils::get_input_value('_list', rcube_utils::INPUT_GPC)) {
+ $settings['selected_list'] = $list;
+ }
+ if ($list && ($id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC))) {
+ $settings['selected_id'] = $id;
+
+ // check if the referenced task is completed
+ $task = $this->plugin->driver->get_task(array('id' => $id, 'list' => $list));
+ console($id, $task);
+ if ($task && $this->plugin->driver->is_complete($task)) {
+ $settings['selected_filter'] = 'complete';
+ }
+ }
+ else if ($filter = rcube_utils::get_input_value('_filter', rcube_utils::INPUT_GPC)) {
+ $settings['selected_filter'] = $filter;
+ }
+
return $settings;
}
More information about the commits
mailing list