plugins/kolab_tags

Aleksander Machniak machniak at kolabsys.com
Fri Jan 9 20:06:29 CET 2015


 plugins/kolab_tags/kolab_tags.js             |  108 ++++++++++++++++++++++++---
 plugins/kolab_tags/lib/kolab_tags_engine.php |   40 +++++++---
 plugins/kolab_tags/localization/en_US.inc    |    1 
 plugins/kolab_tags/skins/larry/style.css     |    8 ++
 4 files changed, 138 insertions(+), 19 deletions(-)

New commits:
commit c9ee78fdd9d8d3aec32497414b5bb0a957e12909
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Fri Jan 9 14:04:12 2015 -0500

    Simplify assigning new tags (#4159)
    
    Added input field to the tag selector popup which can be used
    to search in existing tags or to create a new one (with Enter key)

diff --git a/plugins/kolab_tags/kolab_tags.js b/plugins/kolab_tags/kolab_tags.js
index 9e93af7..bdc5d3a 100644
--- a/plugins/kolab_tags/kolab_tags.js
+++ b/plugins/kolab_tags/kolab_tags.js
@@ -345,6 +345,9 @@ function update_tags(response)
 {
     var list = rcmail.message_list;
 
+    // reset tag selector popup
+    tag_selector_reset();
+
     // remove deleted tags
     remove_tags(response['delete']);
 
@@ -352,6 +355,9 @@ function update_tags(response)
     $.each(response.add || [], function() {
         rcmail.env.tags.push(this);
         add_tag_element($('#taglist'), this, list);
+        if (response.mark) {
+            tag_add_callback(this);
+        }
     });
 
     // update existing tag
@@ -396,9 +402,6 @@ function update_tags(response)
         message_list_select(list);
     }
 
-    // reset tag selector popup
-    tag_selector_element = null;
-
     // @TODO: sort tags by name/prio
 }
 
@@ -471,17 +474,43 @@ function tag_add(props, obj, event)
         return tag_selector(event, function(props) { rcmail.command('tag-add', props); });
     }
 
-    var postdata = rcmail.selection_post_data(),
-        tag = this.tag_find(props),
-        frame_window = rcmail.get_frame_window(rcmail.env.contentframe);
+    var tag, postdata = rcmail.selection_post_data();
+
+    // requested new tag?
+    if (props.name) {
+        postdata._tag = props.name;
+        // find the tag by name to be sure it exists or not
+        if (props = tag_find(props.name, 'name')) {
+            postdata._tag = props.uid;
+        }
+        else {
+            postdata._new = 1;
+        }
+    }
+    else {
+        postdata._tag = props;
+    }
 
-    postdata._tag = props;
     postdata._act = 'add';
 
     rcmail.http_post('plugin.kolab_tags', postdata, true);
 
     // add tags to message(s) without waiting to a response
     // in case of an error the list will be refreshed
+    // this is possible if we use existing tag
+    if (!postdata._new && (tag = this.tag_find(props))) {
+        tag_add_callback(tag);
+    }
+}
+
+// update messages list and message frame after tagging
+function tag_add_callback(tag)
+{
+    if (!tag)
+        return;
+
+    var frame_window = rcmail.get_frame_window(rcmail.env.contentframe);
+
     if (rcmail.message_list) {
         $.each(rcmail.message_list.get_selection(), function (i, uid) {
             var row = rcmail.message_list.rows[uid];
@@ -508,6 +537,16 @@ function tag_remove(props, obj, event)
         return tag_selector(event, function(props) { rcmail.command('tag-remove', props); });
     }
 
+    if (props.name) {
+        // find the tag by name, make sure it exists
+        props = tag_find(props.name, 'name');
+        if (!props) {
+            return;
+        }
+
+        props = props.uid;
+    }
+
     var postdata = rcmail.selection_post_data(),
         tags = props != '*' ? [props] : $.map(rcmail.env.tags, function(tag) { return tag.uid; })
         win = window.parent && parent.rcmail && parent.remove_tags ? parent : window;
@@ -602,10 +641,14 @@ function message_tags(tags, merge)
 }
 
 // return tag info by tag uid
-function tag_find(uid)
+function tag_find(search, key)
 {
+    if (!key) {
+        key = 'uid';
+    }
+
     for (var i in rcmail.env.tags)
-        if (rcmail.env.tags[i].uid == uid)
+        if (rcmail.env.tags[i][key] == search)
             return rcmail.env.tags[i];
 }
 
@@ -663,6 +706,9 @@ function tag_selector(event, callback)
         link.href = '#';
         link.className = 'active';
 
+        // add tag search/create input
+        rows.push(tag_selector_search_element(container));
+
         // loop over tags list
         $.each(rcmail.env.tags, function(i, tag) {
             var a = link.cloneNode(false), row = li.cloneNode(false);
@@ -697,4 +743,48 @@ function tag_selector(event, callback)
     container.data('callback', callback);
 
     rcmail.show_menu('tag-selector', true, event);
+
+    // reset list and search input
+    $('li', container).show();
+    $('input', container).val('').focus();
+}
+
+// remove tag selector element (e.g. after adding/removing a tag)
+function tag_selector_reset()
+{
+    $(tag_selector_element).remove();
+    tag_selector_element = null;
+}
+
+function tag_selector_search_element(container)
+{
+    var input = $('<input>').attr({'type': 'text', title: rcmail.gettext('kolab_tags.tagsearchnew')})
+        .keyup(function(e) {
+            if (this.value) {
+                // execute action on Enter
+                if (e.which == 13) {
+                    container.data('callback')({name: this.value});
+                    rcmail.hide_menu('tag-selector', e);
+                    if ($('#markmessagemenu').is(':visible')) {
+                        rcmail.hide_menu('markmessagemenu', e);
+                    }
+                }
+                // search tags
+                else {
+                    var search = this.value.toUpperCase();
+                    $('li:not(.search)', container).each(function() {
+                        var tag_name = $(this).text().toUpperCase();
+                        $(this)[tag_name.indexOf(search) >= 0 ? 'show' : 'hide']();
+                    });
+                }
+            }
+            else {
+                // reset search
+                $('li', container).show();
+            }
+        });
+
+    return $('<li class="search">').append(input)
+        // prevents from closing the menu on click in the input/row
+        .mouseup(function(e) { return false; });
 }
diff --git a/plugins/kolab_tags/lib/kolab_tags_engine.php b/plugins/kolab_tags/lib/kolab_tags_engine.php
index 52013c8..609e89d 100644
--- a/plugins/kolab_tags/lib/kolab_tags_engine.php
+++ b/plugins/kolab_tags/lib/kolab_tags_engine.php
@@ -54,7 +54,8 @@ class kolab_tags_engine
             $this->plugin->include_script('kolab_tags.js');
             $this->rc->output->add_label('cancel', 'save');
             $this->plugin->add_label('tags', 'add', 'edit', 'delete', 'saving',
-                'nameempty', 'nameexists', 'colorinvalid', 'untag', 'tagname', 'tagcolor');
+                'nameempty', 'nameexists', 'colorinvalid', 'untag', 'tagname',
+                'tagcolor', 'tagsearchnew');
 
             $this->rc->output->add_handlers(array(
                 'plugin.taglist' => array($this, 'taglist'),
@@ -199,8 +200,6 @@ class kolab_tags_engine
     public function action_add()
     {
         $tag     = rcube_utils::get_input_value('_tag', rcube_utils::INPUT_POST);
-        $filter  = array(array('uid', '=', explode(',', $tag)));
-        $taglist = $this->backend->list_tags($filter);
         $storage = $this->rc->get_storage();
         $members = array();
 
@@ -218,24 +217,45 @@ class kolab_tags_engine
             $members = array_merge($members, $this->build_members($mbox, $msgs));
         }
 
-        // for every tag...
-        foreach ($taglist as $tag) {
-            $tag['members'] = array_unique(array_merge((array) $tag['members'], $members));
+        // create a new tag?
+        if (!empty($_POST['_new'])) {
+            $object = array(
+                'name'    => $tag,
+                'members' => $members,
+            );
 
-            // update tag object
-            if (!$this->backend->update($tag)) {
-                $error = true;
+            $object = $this->backend->create($object);
+            $error  = $object === false;
+        }
+        // use existing tags (by UID)
+        else {
+            $filter  = array(array('uid', '=', explode(',', $tag)));
+            $taglist = $this->backend->list_tags($filter);
+
+            // for every tag...
+            foreach ($taglist as $tag) {
+                $tag['members'] = array_unique(array_merge((array) $tag['members'], $members));
+
+                // update tag object
+                if (!$this->backend->update($tag)) {
+                    $error = true;
+                }
             }
         }
 
         if ($error) {
+            $this->rc->output->show_message($this->plugin->gettext('taggingerror'), 'error');
+
             if ($_POST['_from'] != 'show') {
-                $this->rc->output->show_message($this->plugin->gettext('taggingerror'), 'error');
                 $this->rc->output->command('list_mailbox');
             }
         }
         else {
             $this->rc->output->show_message($this->plugin->gettext('taggingsuccess'), 'confirmation');
+
+            if (isset($object)) {
+                $this->rc->output->command('plugin.kolab_tags', array('mark' => 1, 'add' => array($this->parse_tag($object))));
+            }
         }
     }
 
diff --git a/plugins/kolab_tags/localization/en_US.inc b/plugins/kolab_tags/localization/en_US.inc
index a3bcfa1..5c1aa09 100644
--- a/plugins/kolab_tags/localization/en_US.inc
+++ b/plugins/kolab_tags/localization/en_US.inc
@@ -21,6 +21,7 @@ $labels['edit'] = 'Edit';
 $labels['delete'] = 'Delete';
 $labels['tagname'] = 'Name';
 $labels['tagcolor'] = 'Color';
+$labels['tagsearchnew'] = 'Enter text to search or create a new tag';
 $labels['nameempty'] = 'Tag name cannot be empty!';
 $labels['nameexists'] = 'Tag with specified name already exists!';
 $labels['colorinvalid'] = 'Invalid color specification!';
diff --git a/plugins/kolab_tags/skins/larry/style.css b/plugins/kolab_tags/skins/larry/style.css
index 5fffb71..eabfea8 100644
--- a/plugins/kolab_tags/skins/larry/style.css
+++ b/plugins/kolab_tags/skins/larry/style.css
@@ -125,3 +125,11 @@ ul.toolbarmenu li span.icon.tagremoveall {
 	cursor: pointer;
 	text-decoration: none;
 }
+
+#tag-selector li.search {
+	padding: 4px;
+}
+
+#tag-selector li.search input {
+	width: 120px;
+}




More information about the commits mailing list