2 commits - plugins/kolab_addressbook plugins/tasklist

Thomas Brüderli bruederli at kolabsys.com
Thu Jun 21 21:59:35 CEST 2012


 plugins/kolab_addressbook/package.xml                          |   27 -
 plugins/tasklist/drivers/database/tasklist_database_driver.php |   11 
 plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php       |   68 +++
 plugins/tasklist/drivers/tasklist_driver.php                   |   19 
 plugins/tasklist/localization/de_CH.inc                        |    7 
 plugins/tasklist/localization/en_US.inc                        |   93 ++--
 plugins/tasklist/skins/larry/tasklist.css                      |   17 
 plugins/tasklist/skins/larry/templates/mainview.html           |   16 
 plugins/tasklist/tasklist.js                                   |  215 +++++++++-
 plugins/tasklist/tasklist.php                                  |   38 +
 plugins/tasklist/tasklist_ui.php                               |   31 +
 11 files changed, 444 insertions(+), 98 deletions(-)

New commits:
commit 92b2bbead7ae29e5f92dc71773cac835449a7075
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Thu Jun 21 21:59:47 2012 +0200

    Added functions to manage taks lists/folders (aka resources)

diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index 975f96e..5b1e99b 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -75,6 +75,7 @@ class tasklist_database_driver extends tasklist_driver
         while ($result && ($arr = $this->rc->db->fetch_assoc($result))) {
           $arr['showalarms'] = intval($arr['showalarms']);
           $arr['active'] = !in_array($arr['id'], $hidden);
+          $arr['editable'] = true;
           $this->lists[$arr['id']] = $arr;
           $list_ids[] = $this->rc->db->quote($arr['id']);
         }
@@ -133,7 +134,7 @@ class tasklist_database_driver extends tasklist_driver
         $query = $this->rc->db->query(
             "UPDATE " . $this->db_lists . "
              SET   name=?, color=?, showalarms=?
-             WHERE calendar_id=?
+             WHERE tasklist_id=?
              AND   user_id=?",
             $prop['name'],
             $prop['color'],
@@ -288,7 +289,8 @@ class tasklist_database_driver extends tasklist_driver
                 "SELECT * FROM " . $this->db_tasks . "
                  WHERE tasklist_id IN (%s)
                  AND del=0
-                 %s",
+                 %s
+                 ORDER BY parent_id, task_id ASC",
                  join(',', $list_ids),
                  $sql_add
                 ),
@@ -409,6 +411,11 @@ class tasklist_database_driver extends tasklist_driver
                 $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . (empty($prop[$col]) ? 'NULL' : $this->rc->db->quote($prop[$col]));
         }
 
+        // moved from another list
+        if ($prop['_fromlist'] && ($newlist = $prop['list'])) {
+            $sql_set[] = 'tasklist_id=' . $this->rc->db->quote($newlist);
+        }
+
         $query = $this->rc->db->query(sprintf(
             "UPDATE " . $this->db_tasks . "
              SET   changed=%s %s
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 5ccb3de..b1d62eb 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -69,14 +69,27 @@ class tasklist_kolab_driver extends tasklist_driver
 
         asort($names, SORT_LOCALE_STRING);
 
+        $delim = $this->rc->get_storage()->get_hierarchy_delimiter();
+        $listnames = array();
+
         foreach ($names as $utf7name => $name) {
             $folder = $this->folders[$utf7name];
+
+            $path_imap = explode($delim, $name);
+            $editname = array_pop($path_imap);  // pop off raw name part
+            $path_imap = join($delim, $path_imap);
+
+            $name = kolab_storage::folder_displayname(kolab_storage::object_name($utf7name), $listnames);
+
             $tasklist = array(
                 'id' => kolab_storage::folder_id($utf7name),
-                'name' => kolab_storage::object_name($utf7name),
+                'name' => $name,
+                'editname' => $editname,
                 'color' => 'CC0000',
                 'showalarms' => false,
-                'active' => 1, #$folder->is_subscribed(kolab_storage::SERVERSIDE_SUBSCRIPTION),
+                'editable' => true,
+                'active' => $folder->is_subscribed(kolab_storage::SERVERSIDE_SUBSCRIPTION),
+                'parentfolder' => $path_imap,
             );
             $this->lists[$tasklist['id']] = $tasklist;
             $this->folders[$tasklist['id']] = $folder;
@@ -108,7 +121,17 @@ class tasklist_kolab_driver extends tasklist_driver
      */
     public function create_list($prop)
     {
-        return false;
+        $prop['type'] = 'task';
+        $prop['subscribed'] = kolab_storage::SERVERSIDE_SUBSCRIPTION; // subscribe to folder by default
+        $folder = kolab_storage::folder_update($prop);
+
+        if ($folder === false) {
+            $this->last_error = kolab_storage::$last_error;
+            return false;
+        }
+
+        // create ID
+        return kolab_storage::folder_id($folder);
     }
 
     /**
@@ -123,6 +146,20 @@ class tasklist_kolab_driver extends tasklist_driver
      */
     public function edit_list($prop)
     {
+        if ($prop['id'] && ($folder = $this->folders[$prop['id']])) {
+            $prop['oldname'] = $folder->name;
+            $prop['type'] = 'task';
+            $newfolder = kolab_storage::folder_update($prop);
+
+            if ($newfolder === false) {
+                $this->last_error = kolab_storage::$last_error;
+                return false;
+            }
+
+            // create ID
+            return kolab_storage::folder_id($newfolder);
+        }
+
         return false;
     }
 
@@ -136,6 +173,9 @@ class tasklist_kolab_driver extends tasklist_driver
      */
     public function subscribe_list($prop)
     {
+        if ($prop['id'] && ($folder = $this->folders[$prop['id']])) {
+            return $folder->subscribe($prop['active'], kolab_storage::SERVERSIDE_SUBSCRIPTION);
+        }
         return false;
     }
 
@@ -148,6 +188,13 @@ class tasklist_kolab_driver extends tasklist_driver
      */
     public function remove_list($prop)
     {
+        if ($prop['id'] && ($folder = $this->folders[$prop['id']])) {
+          if (kolab_storage::folder_delete($folder->name))
+              return true;
+          else
+              $this->last_error = kolab_storage::$last_error;
+        }
+
         return false;
     }
 
@@ -419,4 +466,19 @@ class tasklist_kolab_driver extends tasklist_driver
     }
 
 
+    /**
+     * 
+     */
+    public function tasklist_edit_form($formfields)
+    {
+        $select = kolab_storage::folder_selector('task', array('name' => 'parent', 'id' => 'edit-parentfolder'), null);
+        $formfields['parent'] = array(
+            'id' => 'edit-parentfolder',
+            'label' => $this->plugin->gettext('parentfolder'),
+            'value' => $select->show(''),
+        );
+        
+        return parent::tasklist_edit_form($formfields);
+    }
+
 }
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index a3b0a85..c1d694d 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -181,4 +181,23 @@ abstract class tasklist_driver
         return $rcmail->config->get('tasklist_categories', array());
     }
 
+    /**
+     * Build the edit/create form for lists.
+     * This gives the drivers the opportunity to add more list properties
+     *
+     * @param array List with form fields to be rendered
+     * @return string HTML content of the form
+     */
+    public function tasklist_edit_form($formfields)
+    {
+        $html = '';
+        foreach ($formfields as $prop => $field) {
+            $html .= html::div('form-section',
+                html::label($field['id'], $field['label']) .
+                $field['value']);
+        }
+
+        return $html;
+    }
+
 }
diff --git a/plugins/tasklist/localization/de_CH.inc b/plugins/tasklist/localization/de_CH.inc
index a7b3712..2253733 100644
--- a/plugins/tasklist/localization/de_CH.inc
+++ b/plugins/tasklist/localization/de_CH.inc
@@ -31,6 +31,13 @@ $labels['save'] = 'Speichern';
 $labels['cancel'] = 'Abbrechen';
 $labels['addsubtask'] = 'Neue Teilaufgabe';
 
+$labels['editlist'] = 'Ressource bearbeiten';
+$labels['createlist'] = 'Neue Ressource';
+$labels['listactions'] = 'Ressourcenoptionen...';
+$labels['listname'] = 'Name';
+$labels['showalarms'] = 'Erinnerungen anzeigen';
+$labels['import'] = 'Importieren';
+
 // date words
 $labels['on'] = 'am';
 $labels['at'] = 'um';
diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc
index cbdcffb..25e374c 100644
--- a/plugins/tasklist/localization/en_US.inc
+++ b/plugins/tasklist/localization/en_US.inc
@@ -1,43 +1,50 @@
-<?php
-
-$labels = array();
-$labels['navtitle'] = 'Tasks';
-$labels['lists'] = 'Resources';
-$labels['list'] = 'Resource';
-
-$labels['createnewtask'] = 'Create new Task';
-$labels['mark'] = 'Mark';
-$labels['unmark'] = 'Unmark';
-$labels['edit'] = 'Edit';
-$labels['delete'] = 'Delete';
-$labels['title'] = 'Title';
-$labels['description'] = 'Description';
-$labels['datetime'] = 'Date/Time';
-
-$labels['all'] = 'All';
-$labels['flagged'] = 'Flagged';
-$labels['complete'] = 'Complete';
-$labels['overdue'] = 'Overdue';
-$labels['today'] = 'Today';
-$labels['tomorrow'] = 'Tomorrow';
-$labels['next7days'] = 'Next 7 days';
-$labels['later'] = 'Later';
-$labels['nodate'] = 'no date';
-
-$labels['taskdetails'] = 'Details';
-$labels['newtask'] = 'New Task';
-$labels['edittask'] = 'Edit Task';
-$labels['save'] = 'Save';
-$labels['cancel'] = 'Cancel';
-$labels['addsubtask'] = 'Add subtask';
-
-// date words
-$labels['on'] = 'on';
-$labels['at'] = 'at';
-$labels['this'] = 'this';
-$labels['next'] = 'next';
-
-// mesages
-$labels['savingdata'] = 'Saving data...';
-$labels['errorsaving'] = 'Failed to save data.';
-$labels['notasksfound'] = 'No tasks found for the given criteria';
+<?php
+
+$labels = array();
+$labels['navtitle'] = 'Tasks';
+$labels['lists'] = 'Resources';
+$labels['list'] = 'Resource';
+
+$labels['createnewtask'] = 'Create new Task';
+$labels['mark'] = 'Mark';
+$labels['unmark'] = 'Unmark';
+$labels['edit'] = 'Edit';
+$labels['delete'] = 'Delete';
+$labels['title'] = 'Title';
+$labels['description'] = 'Description';
+$labels['datetime'] = 'Date/Time';
+
+$labels['all'] = 'All';
+$labels['flagged'] = 'Flagged';
+$labels['complete'] = 'Complete';
+$labels['overdue'] = 'Overdue';
+$labels['today'] = 'Today';
+$labels['tomorrow'] = 'Tomorrow';
+$labels['next7days'] = 'Next 7 days';
+$labels['later'] = 'Later';
+$labels['nodate'] = 'no date';
+
+$labels['taskdetails'] = 'Details';
+$labels['newtask'] = 'New Task';
+$labels['edittask'] = 'Edit Task';
+$labels['save'] = 'Save';
+$labels['cancel'] = 'Cancel';
+$labels['addsubtask'] = 'Add subtask';
+
+$labels['editlist'] = 'Edit resource';
+$labels['createlist'] = 'Add resource';
+$labels['listactions'] = 'Resource options...';
+$labels['listname'] = 'Name';
+$labels['showalarms'] = 'Show alarms';
+$labels['import'] = 'Import';
+
+// date words
+$labels['on'] = 'on';
+$labels['at'] = 'at';
+$labels['this'] = 'this';
+$labels['next'] = 'next';
+
+// mesages
+$labels['savingdata'] = 'Saving data...';
+$labels['errorsaving'] = 'Failed to save data.';
+$labels['notasksfound'] = 'No tasks found for the given criteria';
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index 8811766..f32f2bd 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -64,10 +64,6 @@ body.tasklistview #searchmenulink {
 	border-radius: 0 0 4px 4px;
 }
 
-#taskselector li.selected {
-	background-color: #c7e3ef;
-}
-
 #taskselector li.overdue a {
 	color: #b72a2a;
 	font-weight: bold;
@@ -160,14 +156,6 @@ body.tasklistview #searchmenulink {
 	right: 5px;
 }
 
-#tasklists li.selected {
-	background-color: #c7e3ef;
-}
-
-#tasklists li.selected span.calname {
-	font-weight: bold;
-}
-
 #mainview-right {
 	position: absolute;
 	top: 0;
@@ -461,6 +449,11 @@ ul.toolbarmenu li span.delete {
 	color: #999;
 }
 
+#task-parent-title {
+	position: relative;
+	top: -0.6em;
+}
+
 a.morelink {
 	font-size: 90%;
 	color: #0069a6;
diff --git a/plugins/tasklist/skins/larry/templates/mainview.html b/plugins/tasklist/skins/larry/templates/mainview.html
index fd8fa5c..b44d976 100644
--- a/plugins/tasklist/skins/larry/templates/mainview.html
+++ b/plugins/tasklist/skins/larry/templates/mainview.html
@@ -74,7 +74,19 @@
 	</ul>
 </div>
 
+<div id="tasklistoptionsmenu" class="popupmenu">
+	<ul class="toolbarmenu">
+		<li><roundcube:button command="list-edit" label="edit" classAct="active" /></li>
+		<li><roundcube:button command="list-remove" label="delete" classAct="active" /></li>
+		<li><roundcube:button command="list-import" label="tasklist.import" classAct="active" /></li>
+		<roundcube:if condition="env:tasklist_driver == 'kolab'" />
+		<li><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
+		<roundcube:endif />
+	</ul>
+</div>
+
 <div id="taskshow">
+	<div class="form-section" id="task-parent-title"></div>
 	<div class="form-section">
 		<h2 id="task-title"></h2>
 	</div>
@@ -125,6 +137,10 @@
 	</form>
 </div>
 
+<div id="tasklistform" class="uidialog">
+	<roundcube:object name="plugin.tasklist_editform" />
+</div>
+
 <script type="text/javascript">
 
 // UI startup
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index c76e411..7865e1a 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -49,7 +49,6 @@ function rcube_tasklist(settings)
     var selector = 'all';
     var filtermask = FILTER_MASK_ALL;
     var idcount = 0;
-    var selected_list;
     var saving_lock;
     var ui_loading;
     var taskcounts = {};
@@ -77,6 +76,7 @@ function rcube_tasklist(settings)
     /*  public members  */
     this.tasklists = rcmail.env.tasklists;
     this.selected_task;
+    this.selected_list;
 
     /*  public methods  */
     this.init = init;
@@ -85,6 +85,8 @@ function rcube_tasklist(settings)
     this.add_childtask = add_childtask;
     this.quicksearch = quicksearch;
     this.reset_search = reset_search;
+    this.list_remove = list_remove;
+    this.list_edit_dialog = list_edit_dialog;
 
 
     /**
@@ -92,16 +94,25 @@ function rcube_tasklist(settings)
      */
     function init()
     {
-        // select the first task list
-        for (var s in me.tasklists) {
-            selected_list = s;
-            break;
-        };
+        // sinitialize task list selectors
+        for (var id in me.tasklists) {
+            if ((li = rcmail.get_folder_li(id, 'rcmlitasklist'))) {
+                init_tasklist_li(li, id);
+            }
+
+            if (!me.tasklists.readonly && !me.selected_list) {
+                me.selected_list = id;
+                rcmail.enable_command('addtask', true);
+                $(li).click();
+            }
+        }
 
         // register server callbacks
         rcmail.addEventListener('plugin.data_ready', data_ready);
         rcmail.addEventListener('plugin.refresh_task', update_taskitem);
         rcmail.addEventListener('plugin.update_counts', update_counts);
+        rcmail.addEventListener('plugin.insert_tasklist', insert_list);
+        rcmail.addEventListener('plugin.update_tasklist', update_list);
         rcmail.addEventListener('plugin.reload_data', function(){ list_tasks(null); });
         rcmail.addEventListener('plugin.unlock_saving', function(p){ rcmail.set_busy(false, null, saving_lock); });
 
@@ -121,7 +132,7 @@ function rcube_tasklist(settings)
             var tasktext = this.elements.text.value;
             var rec = { id:-(++idcount), title:tasktext, readonly:true, mask:0, complete:0 };
 
-            save_task({ tempid:rec.id, raw:tasktext, list:selected_list }, 'new');
+            save_task({ tempid:rec.id, raw:tasktext, list:me.selected_list }, 'new');
             render_task(rec);
 
             // clear form
@@ -255,7 +266,11 @@ function rcube_tasklist(settings)
      */
     function fetch_counts()
     {
-        rcmail.http_request('counts');
+        var active = active_lists();
+        if (active.length)
+            rcmail.http_request('counts', { lists:active.join(',') });
+        else
+            update_counts({});
     }
 
     /**
@@ -268,8 +283,13 @@ function rcube_tasklist(settings)
             selector = sel;
         }
 
-        ui_loading = rcmail.set_busy(true, 'loading');
-        rcmail.http_request('fetch', { filter:filtermask, q:search_query }, true);
+        var active = active_lists();
+        if (active.length) {
+            ui_loading = rcmail.set_busy(true, 'loading');
+            rcmail.http_request('fetch', { filter:filtermask, lists:active.join(','), q:search_query }, true);
+        }
+        else
+            data_ready([]);
 
         $('#taskselector li.selected').removeClass('selected');
         $('#taskselector li.'+selector).addClass('selected');
@@ -373,7 +393,7 @@ function rcube_tasklist(settings)
             div.addClass('nodate');
         if ((rec.mask & FILTER_MASK_OVERDUE))
             div.addClass('overdue');
-console.log(replace)
+
         var li, parent;
         if (replace && (li = $('li[rel="'+replace+'"]', rcmail.gui_objects.resultlist)) && li.length) {
             li.children('div.taskhead').first().replaceWith(div);
@@ -545,6 +565,7 @@ console.log(replace)
         me.selected_task = rec;
 
         // fill dialog data
+        $('#task-parent-title').html(Q(rec.parent_title || '')+' »').css('display', rec.parent_title ? 'block' : 'none');
         $('#task-title').html(Q(rec.title || ''));
         $('#task-description').html(text2html(rec.description || '', 300, 6))[(rec.description ? 'show' : 'hide')]();
         $('#task-date')[(rec.date ? 'show' : 'hide')]().children('.task-text').html(Q(rec.date || rcmail.gettext('nodate','tasklist')));
@@ -590,7 +611,7 @@ console.log(replace)
             $dialog = $('<div>'),
             editform = $('#taskedit'),
             list = rec.list && me.tasklists[rec.list] ? me.tasklists[rec.list] :
-                (selected_list ? me.tasklists[selected_list] : { editable: action=='new' });
+                (me.selected_list ? me.tasklists[me.selected_list] : { editable: action=='new' });
 
         if (list.readonly || (action == 'edit' && (!rec || rec.readonly || rec.temp)))
             return false;
@@ -604,7 +625,7 @@ console.log(replace)
         var rectime = $('#edit-time').val(rec.time || '');
         var complete = $('#edit-completeness').val((rec.complete || 0) * 100);
         completeness_slider.slider('value', complete.val());
-        var tasklist = $('#edit-tasklist').val(rec.list || 0);
+        var tasklist = $('#edit-tasklist').val(rec.list || 0); // .prop('disabled', rec.parent_id ? true : false);
 
         $('#edit-nodate').unbind('click').click(function(){
             recdate.val('');
@@ -698,6 +719,108 @@ console.log(replace)
     }
 
     /**
+     *
+     */
+    function list_edit_dialog(id)
+    {
+        var list = me.tasklists[id],
+            $dialog = $('#tasklistform').dialog('close');
+            editform = $('#tasklisteditform');
+
+        if (!list)
+            list = { name:'', editable:true, showalarms:true };
+
+        // fill edit form
+        var name = $('#edit-tasklistame').prop('disabled', !list.editable).val(list.editname || list.name),
+            alarms = $('#edit-showalarms').prop('checked', list.showalarms).get(0),
+            parent = $('#edit-parentfolder').val(list.parentfolder);
+
+        // dialog buttons
+        var buttons = {};
+
+        buttons[rcmail.gettext('save','tasklist')] = function() {
+          // do some input validation
+          if (!name.val() || name.val().length < 2) {
+            alert(rcmail.gettext('invalidlistproperties', 'tasklist'));
+            name.select();
+            return;
+          }
+
+          // post data to server
+          var data = editform.serializeJSON();
+          if (list.id)
+            data.id = list.id;
+          if (alarms)
+            data.showalarms = alarms.checked ? 1 : 0;
+        if (parent.length)
+            data.parentfolder = $('option:selected', parent).val();
+
+          saving_lock = rcmail.set_busy(true, 'tasklist.savingdata');
+          rcmail.http_post('tasklist', { action:(list.id ? 'edit' : 'new'), l:data });
+          $dialog.dialog('close');
+        };
+
+        buttons[rcmail.gettext('cancel','tasklist')] = function() {
+          $dialog.dialog('close');
+        };
+
+        // open jquery UI dialog
+        $dialog.dialog({
+          modal: true,
+          resizable: true,
+          closeOnEscape: false,
+          title: rcmail.gettext((list.id ? 'editlist' : 'createlist'), 'tasklist'),
+          close: function() { $dialog.dialog('destroy').hide(); },
+          buttons: buttons,
+          minWidth: 400,
+          width: 420
+        }).show();
+    }
+
+    /**
+     *
+     */
+    function list_remove(id)
+    {
+        var list = me.tasklists[id];
+        if (list && !list.readonly) {
+            alert('To be implemented')
+        }
+    }
+
+    /**
+     *
+     */
+    function insert_list(prop)
+    {
+        console.log(prop)
+        var li = $('<li>').attr('id', 'rcmlitasklist'+prop.id)
+            .append('<input type="checkbox" name="_list[]" value="'+prop.id+'" checked="checked" />')
+            .append('<span class="handle"> </span>')
+            .append('<span class="listname">'+Q(prop.name)+'</span>');
+        $(rcmail.gui_objects.folderlist).append(li);
+        init_tasklist_li(li.get(0), prop.id);
+        me.tasklists[prop.id] = prop;
+    }
+
+    /**
+     *
+     */
+    function update_list(prop)
+    {
+        var id = prop.oldid || prop.id,
+            li = rcmail.get_folder_li(id, 'rcmlitasklist');
+
+        if (me.tasklists[id] && li) {
+            delete me.tasklists[id];
+            me.tasklists[prop.id] = prop;
+            $(li).data('id', prop.id);
+            $('#'+li.id+' input').data('id', prop.id);
+            $('.listname', li).html(Q(prop.name));
+        }
+    }
+
+    /**
      * Execute search
      */
     function quicksearch()
@@ -828,10 +951,13 @@ console.log(replace)
      */
     function clear_popups(e)
     {
-        var count = 0;
+        var count = 0, target = e.target;
+        if (target && target.className == 'inner')
+            target = e.target.parentNode;
+
         $('.popupmenu:visible').each(function(i, elem){
-            var menu = $(elem);
-            if (!menu.data('sticky') || !target_overlaps(e.target, elem)) {
+            var menu = $(elem), id = elem.id;
+            if (target.id != id+'link' && (!menu.data('sticky') || !target_overlaps(e.target, elem))) {
                 menu.hide();
                 count++;
             }
@@ -852,9 +978,58 @@ console.log(replace)
         return false;
     }
 
+    /**
+     *
+     */
+    function active_lists()
+    {
+        var active = [];
+        for (var id in me.tasklists) {
+            if (me.tasklists[id].active)
+                active.push(id);
+        }
+        return active;
+    }
+
+    /**
+     * Register event handlers on a tasklist (folder) item
+     */
+    function init_tasklist_li(li, id)
+    {
+        $('#'+li.id+' input').click(function(e){
+            var id = $(this).data('id');
+            if (me.tasklists[id]) {  // add or remove event source on click
+                me.tasklists[id].active = this.checked;
+                fetch_counts();
+                list_tasks(null);
+                rcmail.http_post('tasklist', { action:'subscribe', l:{ id:id, active:me.tasklists[id].active?1:0 } });
+            }
+        }).data('id', id).get(0).checked = me.tasklists[id].active || false;
+
+        $(li).click(function(e){
+            var id = $(this).data('id');
+            rcmail.select_folder(id, 'rcmlitasklist');
+            rcmail.enable_command('list-edit', 'list-remove', 'import', !me.tasklists[id].readonly);
+            me.selected_list = id;
+      })
+//              .dblclick(function(){ list_edit_dialog(me.selected_list); })
+      .data('id', id);
+    }
 }
 
 
+// extend jQuery
+(function($){
+  $.fn.serializeJSON = function(){
+    var json = {};
+    jQuery.map($(this).serializeArray(), function(n, i) {
+      json[n['name']] = n['value'];
+    });
+    return json;
+  };
+})(jQuery);
+
+
 /* tasklist plugin UI initialization */
 var rctasks;
 window.rcmail && rcmail.addEventListener('init', function(evt) {
@@ -862,8 +1037,12 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
   rctasks = new rcube_tasklist(rcmail.env.tasklist_settings);
 
   // register button commands
-  //rcmail.register_command('addtask', function(){ tasks.add_task(); }, true);
-  //rcmail.register_command('print', function(){ tasks.print_list(); }, true);
+  //rcmail.register_command('addtask', function(){ rctasks.add_task(); }, true);
+  //rcmail.register_command('print', function(){ rctasks.print_list(); }, true);
+
+  rcmail.register_command('list-create', function(){ rctasks.list_edit_dialog(null); }, true);
+  rcmail.register_command('list-edit', function(){ rctasks.list_edit_dialog(rctasks.selected_list); }, false);
+  rcmail.register_command('list-remove', function(){ rctasks.list_remove(rctasks.selected_list); }, false);
 
   rcmail.register_command('search', function(){ rctasks.quicksearch(); }, true);
   rcmail.register_command('reset-search', function(){ rctasks.reset_search(); }, true);
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 2a2d815..27a5644 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -273,14 +273,39 @@ class tasklist extends rcube_plugin
         $list  = get_input_value('l', RCUBE_INPUT_POST, true);
         $success = false;
 
+        if (isset($list['showalarms']))
+          $list['showalarms'] = intval($list['showalarms']);
+
         switch ($action) {
-            
+        case 'new':
+            $list += array('showalarms' => true, 'active' => true);
+            if ($insert_id = $this->driver->create_list($list)) {
+                $list['id'] = $insert_id;
+                $this->rc->output->command('plugin.insert_tasklist', $list);
+                $success = true;
+            }
+            break;
+
+        case 'edit':
+            if ($newid = $this->driver->edit_list($list)) {
+                $list['oldid'] = $list['id'];
+                $list['id'] = $newid;
+                $this->rc->output->command('plugin.update_tasklist', $list);
+                $success = true;
+            }
+            break;
+
+        case 'subscribe':
+            $success = $this->driver->subscribe_list($list);
+            break;
         }
 
         if ($success)
             $this->rc->output->show_message('successfullysaved', 'confirmation');
         else
             $this->rc->output->show_message('tasklist.errorsaving', 'error');
+
+        $this->rc->output->command('plugin.unlock_saving');
     }
 
     /**
@@ -314,7 +339,7 @@ class tasklist extends rcube_plugin
         $f = intval(get_input_value('filter', RCUBE_INPUT_GPC));
         $search = get_input_value('q', RCUBE_INPUT_GPC);
         $filter = array('mask' => $f, 'search' => $search);
-        $lists = null;
+        $lists = get_input_value('lists', RCUBE_INPUT_GPC);;
 
         // convert magic date filters into a real date range
         switch ($f) {
@@ -347,10 +372,9 @@ class tasklist extends rcube_plugin
 
         }
 
-        $data = $this->task_tree = $this->tasks_childs = array();
+        $data = $this->task_tree = $this->task_titles = array();
         foreach ($this->driver->list_tasks($filter, $lists) as $rec) {
             if ($rec['parent_id']) {
-                $this->tasks_childs[$rec['parent_id']]++;
                 $this->task_tree[$rec['id']] = $rec['parent_id'];
             }
             $this->encode_task($rec);
@@ -391,17 +415,17 @@ class tasklist extends rcube_plugin
             $rec['_hasdate'] = 0;
         }
 
-        if ($this->tasks_childs[$rec['id']])
-            $rec['_haschilds'] = $this->tasks_childs[$rec['id']];
-
         if (!isset($rec['_depth'])) {
             $rec['_depth'] = 0;
             $parent_id = $this->task_tree[$rec['id']];
             while ($parent_id) {
                 $rec['_depth']++;
+                $rec['parent_title'] = $this->task_titles[$parent_id];
                 $parent_id = $this->task_tree[$parent_id];
             }
         }
+
+        $this->task_titles[$rec['id']] = $rec['title'];
     }
 
     /**
diff --git a/plugins/tasklist/tasklist_ui.php b/plugins/tasklist/tasklist_ui.php
index 50ae64a..b623295 100644
--- a/plugins/tasklist/tasklist_ui.php
+++ b/plugins/tasklist/tasklist_ui.php
@@ -66,6 +66,7 @@ class tasklist_ui
         $this->plugin->register_handler('plugin.category_select', array($this, 'category_select'));
         $this->plugin->register_handler('plugin.searchform', array($this->rc->output, 'search_form'));
         $this->plugin->register_handler('plugin.quickaddform', array($this, 'quickadd_form'));
+        $this->plugin->register_handler('plugin.tasklist_editform', array($this, 'tasklist_editform'));
         $this->plugin->register_handler('plugin.tasks', array($this, 'tasks_resultview'));
 
         $this->plugin->include_script('tasklist.js');
@@ -108,7 +109,7 @@ class tasklist_ui
                 $class .= ' '.$prop['class_name'];
 
             $li .= html::tag('li', array('id' => 'rcmlitasklist' . $html_id, 'class' => $class),
-                html::tag('input', array('type' => 'checkbox', 'name' => '_list[]', 'value' => $id, 'checked' => $prop['active'], 'disabled' => true)) .
+                html::tag('input', array('type' => 'checkbox', 'name' => '_list[]', 'value' => $id, 'checked' => $prop['active'])) .
                 html::span('handle', ' ') .
                 html::span('listname', Q($prop['name'])));
         }
@@ -135,6 +136,34 @@ class tasklist_ui
         return $select->show(null);
     }
 
+
+    function tasklist_editform($attrib = array())
+    {
+        $fields = array(
+            'name' => array(
+                'id' => 'edit-tasklistame',
+                'label' => $this->plugin->gettext('listname'),
+                'value' => html::tag('input', array('id' => 'edit-tasklistame', 'name' => 'name', 'type' => 'text', 'class' => 'text', 'size' => 40)),
+            ),
+/*
+            'color' => array(
+                'id' => 'edit-color',
+                'label' => $this->plugin->gettext('color'),
+                'value' => html::tag('input', array('id' => 'edit-color', 'name' => 'color', 'type' => 'text', 'class' => 'text colorpicker', 'size' => 6)),
+            ),
+            'showalarms' => array(
+                'id' => 'edit-showalarms',
+                'label' => $this->plugin->gettext('showalarms'),
+                'value' => html::tag('input', array('id' => 'edit-showalarms', 'name' => 'color', 'type' => 'checkbox')),
+            ),
+*/
+        );
+
+        return html::tag('form', array('action' => "#", 'method' => "post", 'id' => 'tasklisteditform'),
+            $this->plugin->driver->tasklist_edit_form($fields)
+        );
+    }
+
     /**
      * Render a HTML select box to select a task category
      */


commit dc3fa5cb4b347bd96b914cf429db1f4fcddbee67
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Thu Jun 21 21:39:28 2012 +0200

    Update package.xml

diff --git a/plugins/kolab_addressbook/package.xml b/plugins/kolab_addressbook/package.xml
index 9d43c65..61015a7 100644
--- a/plugins/kolab_addressbook/package.xml
+++ b/plugins/kolab_addressbook/package.xml
@@ -4,12 +4,12 @@
     http://pear.php.net/dtd/package-2.0
     http://pear.php.net/dtd/package-2.0.xsd">
 	<name>kolab_addressbook</name>
-    <uri>http://git.kolab.org/roundcubemail-plugins-kolab/</uri>
+	<uri>http://git.kolab.org/roundcubemail-plugins-kolab/</uri>
 	<summary>Kolab addressbook</summary>
 	<description>
-	    Sample plugin to add a new address book source with data from Kolab storage.
-        It provides also a possibilities to manage contact folders
-        (create/rename/delete/acl) directly in Addressbook UI.
+		Sample plugin to add a new address book source with data from Kolab storage.
+		It provides also a possibilities to manage contact folders
+		(create/rename/delete/acl) directly in Addressbook UI.
 	</description>
 	<lead>
 		<name>Aleksander Machniak</name>
@@ -23,10 +23,10 @@
 		<email>bruederli at kolabsys.com</email>
 		<active>yes</active>
 	</lead>
-	<date>2011-11-01</date>
+	<date>2012-06-21</date>
 	<version>
-		<release>0.6</release>
-		<api>0.6</api>
+		<release>0.9</release>
+		<api>0.9</api>
 	</version>
 	<stability>
 		<release>stable</release>
@@ -48,7 +48,10 @@
 			<file name="skins/default/kolab_folders.gif" role="data"></file>
 			<file name="skins/default/kolab_folders.png" role="data"></file>
 			<file name="skins/default/templates/bookedit.html" role="data"></file>
-
+			<file name="skins/larry/kolab_addressbook.css" role="data"></file>
+			<file name="skins/larry/templates/bookedit.html" role="data"></file>
+			<file name="localization/de_CH.inc" role="data"></file>
+			<file name="localization/de_DE.inc" role="data"></file>
 			<file name="localization/en_US.inc" role="data"></file>
 			<file name="localization/ja_JP.inc" role="data"></file>
 			<file name="localization/pl_PL.inc" role="data"></file>
@@ -64,10 +67,10 @@
 			<pearinstaller>
 				<min>1.7.0</min>
 			</pearinstaller>
-            <package>
-                <name>kolab_core</name>
-                <uri>http://kolabsys.com</uri>
-            </package>
+			<package>
+				<name>libkolab</name>
+				<uri>http://git.kolab.org/roundcubemail-plugins-kolab/tree/plugins/libkolab</uri>
+			</package>
 		</required>
 	</dependencies>
 	<phprelease/>





More information about the commits mailing list