4 commits - plugins/calendar plugins/libcalendaring plugins/tasklist

Thomas Brüderli bruederli at kolabsys.com
Tue Aug 19 10:39:06 CEST 2014


 plugins/calendar/calendar.php                        |    4 -
 plugins/calendar/calendar_ui.js                      |   30 +++++++--
 plugins/calendar/skins/larry/calendar.css            |   59 ++++++++++++-------
 plugins/calendar/skins/larry/images/autocomplete.png |binary
 plugins/libcalendaring/libcalendaring.js             |   59 +++++++++++++++++++
 plugins/libcalendaring/libcalendaring.php            |   56 ++++++++++++++++++
 plugins/libcalendaring/localization/en_US.inc        |    6 +
 plugins/tasklist/skins/larry/tasklist.css            |   45 ++++++++------
 plugins/tasklist/tasklist.js                         |   45 +++++++++-----
 plugins/tasklist/tasklist.php                        |    2 
 10 files changed, 240 insertions(+), 66 deletions(-)

New commits:
commit ff9f87a037687a62dbd0070a6d2582fb9ec14d3b
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 19 10:37:31 2014 +0200

    Add button to expand members of a group attendee (#3376); prefix edit-attendees-table styles to avoid unintended style overrides

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 840a2ed..4975f7c 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -294,7 +294,7 @@ class calendar extends rcube_plugin
 
     $this->ui->init_templates();
     $this->rc->output->add_label('lowest','low','normal','high','highest','delete','cancel','uploading','noemailwarning','close');
-    $this->rc->output->add_label('libcalendaring.itipaccepted','libcalendaring.itiptentative','libcalendaring.itipdeclined','libcalendaring.itipdelegated');
+    $this->rc->output->add_label('libcalendaring.itipaccepted','libcalendaring.itiptentative','libcalendaring.itipdeclined','libcalendaring.itipdelegated','libcalendaring.expandattendeegroup','libcalendaring.expandattendeegroupnodata');
 
     // initialize attendees autocompletion
     rcube_autocomplete_init();
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index c41bd96..1b3547d 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -914,11 +914,11 @@ function rcube_calendar_ui(settings)
         },
         buttons: buttons,
         minWidth: 500,
-        width: 580
+        width: 600
       }).append(editform.show());  // adding form content AFTERWARDS massively speeds up opening on IE6
 
       // set dialog size according to form content
-      me.dialog_resize($dialog.get(0), editform.height() + (bw.ie ? 20 : 0), 530);
+      me.dialog_resize($dialog.get(0), editform.height() + (bw.ie ? 20 : 0), 550);
 
       title.select();
 
@@ -1877,7 +1877,7 @@ function rcube_calendar_ui(settings)
     };
 
     // add the given attendee to the list
-    var add_attendee = function(data, readonly)
+    var add_attendee = function(data, readonly, before)
     {
       if (!me.selected_event)
         return false;
@@ -1931,6 +1931,12 @@ function rcube_calendar_ui(settings)
       else if (data['delegated-from'])
         tooltip = rcmail.gettext('delegatedfrom', 'calendar') + data['delegated-from'];
 
+      // add expand button for groups
+      if (data.cutype == 'GROUP') {
+        dispname += ' <a href="#expand" data-email="' + Q(data.email) + '" class="iconbutton add expandlink" title="' + rcmail.gettext('expandattendeegroup','libcalendaring') + '">' +
+          rcmail.gettext('expandattendeegroup','libcalendaring') + '</a>';
+      }
+
       var html = '<td class="role">' + select + '</td>' +
         '<td class="name">' + dispname + '</td>' +
         '<td class="availability"><img src="./program/resources/blank.gif" class="availabilityicon ' + avail + '" data-email="' + data.email + '" alt="" /></td>' +
@@ -1941,11 +1947,16 @@ function rcube_calendar_ui(settings)
       var table = rcmail.env.calendar_resources && data.cutype == 'RESOURCE' ? resources_list : attendees_list;
       var tr = $('<tr>')
         .addClass(String(data.role).toLowerCase())
-        .html(html)
-        .appendTo(table);
+        .html(html);
+
+      if (before)
+        tr.insertBefore(before)
+      else
+        tr.appendTo(table);
 
       tr.find('a.deletelink').click({ id:(data.email || data.name) }, function(e) { remove_attendee(this, e.data.id); return false; });
       tr.find('a.mailtolink').click(event_attendee_click);
+      tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); });
       tr.find('input.edit-attendee-reply').click(function() {
         var enabled = $('#edit-attendees-invite:checked').length || $('input.edit-attendee-reply:checked').length;
         $('p.attendees-commentbox')[enabled ? 'show' : 'hide']();
@@ -3755,12 +3766,15 @@ function rcube_calendar_ui(settings)
         };
       }
       rcmail.init_address_input_events($('#edit-attendee-name'), ac_props);
-      rcmail.addEventListener('autocomplete_insert', function(e){
+      rcmail.addEventListener('autocomplete_insert', function(e) {
+        var success = false;
         if (e.field.name == 'participant') {
-          $('#edit-attendee-add').click();
+          success = add_attendees(e.insert, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:(e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL') });
         }
         else if (e.field.name == 'resource' && e.data && e.data.email) {
-          add_attendee($.extend(e.data, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'RESOURCE' }));
+          success = add_attendee($.extend(e.data, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'RESOURCE' }));
+        }
+        if (e.field && success) {
           e.field.value = '';
         }
       });
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 85a7aa5..0700455 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -955,31 +955,31 @@ td.topalign {
 	width: 95%;
 }
 
-.edit-attendees-table {
+#eventedit .edit-attendees-table {
 	width: 100%;
 	margin-top: 0.5em;
 }
 
-.edit-attendees-table th.role,
-.edit-attendees-table td.role {
+#eventedit .edit-attendees-table th.role,
+#eventedit .edit-attendees-table td.role {
 	width: 9em;
 }
 
-.edit-attendees-table th.availability,
-.edit-attendees-table td.availability,
-.edit-attendees-table th.confirmstate,
-.edit-attendees-table td.confirmstate {
+#eventedit .edit-attendees-table th.availability,
+#eventedit .edit-attendees-table td.availability,
+#eventedit .edit-attendees-table th.confirmstate,
+#eventedit .edit-attendees-table td.confirmstate {
 	width: 4em;
 }
 
-.edit-attendees-table th.options,
-.edit-attendees-table td.options {
+#eventedit .edit-attendees-table th.options,
+#eventedit .edit-attendees-table td.options {
 	width: 16px;
 	padding: 2px 4px;
 }
 
-.edit-attendees-table th.sendmail,
-.edit-attendees-table td.sendmail {
+#eventedit .edit-attendees-table th.sendmail,
+#eventedit .edit-attendees-table td.sendmail {
 	width: 44px;
 	padding: 2px;
 }
@@ -998,23 +998,24 @@ td.topalign {
 	background: url(images/sendinvitation.png) 1px 0 no-repeat;
 }
 
-.edit-attendees-table tbody tr:last-child td {
+#eventedit .edit-attendees-table tbody tr:last-child td {
 	border-bottom: 0;
 }
 
-.edit-attendees-table th.name,
-.edit-attendees-table td.name {
+#eventedit .edit-attendees-table th.name,
+#eventedit .edit-attendees-table td.name {
 	width: auto;
 	white-space: nowrap;
 	overflow: hidden;
 	text-overflow: ellipsis;
+	position: relative;
 }
 
-.edit-attendees-table td.name select {
+#eventedit .edit-attendees-table td.name select {
 	width: 100%;
 }
 
-.edit-attendees-table a.deletelink {
+#eventedit .edit-attendees-table a.deletelink {
 	display: inline-block;
 	width: 17px;
 	height: 17px;
@@ -1023,6 +1024,14 @@ td.topalign {
 	text-indent: 1000px;
 }
 
+#eventedit .edit-attendees-table a.expandlink {
+	position: absolute;
+	top: 4px;
+	right: 6px;
+	width: 16px;
+	height: 16px;
+}
+
 #edit-attendees-form,
 #edit-resources-form {
 	position: relative;
diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index 6f20ab7..39b34ae 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -33,6 +33,7 @@ function rcube_libcalendaring(settings)
     this.alarm_dialog = null;
     this.snooze_popup = null;
     this.dismiss_link = null;
+    this.group2expand = {};
 
     // abort if env isn't set
     if (!settings || !settings.date_format)
@@ -729,6 +730,64 @@ function rcube_libcalendaring(settings)
         $.each(listitems, function(idx, item) { mylist.append(item); });
     };
 
+
+    /*****  Attendee form handling  *****/
+
+    // expand the given contact group into individual event/task attendees
+    this.expand_attendee_group = function(e, add, remove)
+    {
+        var id = (e.data ? e.data.email : null) || $(e.target).attr('data-email'),
+            role_select = $(e.target).closest('tr').find('select.edit-attendee-role option:selected');
+
+        this.group2expand[id] = { link: e.target, data: $.extend({}, e.data || {}), adder: add, remover: remove }
+
+        // copy group role from the according form element
+        if (role_select.length) {
+            this.group2expand[id].data.role = role_select.val();
+        }
+
+        // register callback handler
+        if (!this._expand_attendee_listener) {
+            this._expand_attendee_listener = this.expand_attendee_callback;
+            rcmail.addEventListener('plugin.expand_attendee_callback', function(result) {
+                me._expand_attendee_listener(result);
+            });
+        }
+
+        rcmail.http_post('libcal/plugin.expand_attendee_group', { id: id, data: e.data || {} }, rcmail.set_busy(true, 'loading'));
+    };
+
+    // callback from server to expand an attendee group
+    this.expand_attendee_callback = function(result)
+    {
+        var attendee, id = result.id,
+            data = this.group2expand[id],
+            row = $(data.link).closest('tr');
+
+        // replace group entry with all members returned by the server
+        if (data && data.adder && result.members && result.members.length) {
+            for (var i=0; i < result.members.length; i++) {
+                attendee = result.members[i];
+                attendee.role = data.data.role;
+                attendee.cutype = 'INDIVIDUAL';
+                attendee.status = 'NEEDS-ACTION';
+                data.adder(attendee, null, row);
+            }
+
+            if (data.remover) {
+                data.remover(data.link, id)
+            }
+            else {
+                row.remove();
+            }
+
+            delete this.group2expand[id];
+        }
+        else {
+            rcmail.display_message(result.error || rcmail.gettext('expandattendeegroupnodata','libcalendaring'), 'error');
+        }
+    };
+
 }
 
 //////  static methods
diff --git a/plugins/libcalendaring/libcalendaring.php b/plugins/libcalendaring/libcalendaring.php
index 6ca548e..52a8134 100644
--- a/plugins/libcalendaring/libcalendaring.php
+++ b/plugins/libcalendaring/libcalendaring.php
@@ -106,6 +106,7 @@ class libcalendaring extends rcube_plugin
             // add hook to display alarms
             $this->add_hook('refresh', array($this, 'refresh'));
             $this->register_action('plugin.alarms', array($this, 'alarms_action'));
+            $this->register_action('plugin.expand_attendee_group', array($this, 'expand_attendee_group'));
         }
 
         // proceed initialization in startup hook
@@ -1359,6 +1360,61 @@ class libcalendaring extends rcube_plugin
     }
 
 
+    /*********  Attendee handling functions  *********/
+
+    /**
+     * Handler for attendee group expansion requests
+     */
+    public function expand_attendee_group()
+    {
+        $id     = rcube_utils::get_input_value('id', rcube_utils::INPUT_POST);
+        $data   = rcube_utils::get_input_value('data', rcube_utils::INPUT_POST, true);
+        $result = array('id' => $id, 'members' => array());
+        $maxnum = 500;
+
+        // iterate over all autocomplete address books (we don't know the source of the group)
+        foreach ((array)$this->rc->config->get('autocomplete_addressbooks', 'sql') as $abook_id) {
+            if (($abook = $this->rc->get_address_book($abook_id)) && $abook->groups) {
+                foreach ($abook->list_groups($data['name'], 1) as $group) {
+                    // this is the matching group to expand
+                    if (in_array($data['email'], (array)$group['email'])) {
+                        $abook->set_pagesize($maxnum);
+                        $abook->set_group($group['ID']);
+
+                        // get all members
+                        $res = $abook->list_records($this->rc->config->get('contactlist_fields'));
+
+                        // handle errors (e.g. sizelimit, timelimit)
+                        if ($abook->get_error()) {
+                            $result['error'] = $this->rc->gettext('expandattendeegrouperror', 'libcalendaring');
+                            $res = false;
+                        }
+                        // check for maximum number of members (we don't wanna bloat the UI too much)
+                        else if ($res->count > $maxnum) {
+                            $result['error'] = $this->rc->gettext('expandattendeegroupsizelimit', 'libcalendaring');
+                            $res = false;
+                        }
+
+                        while ($res && ($member = $res->iterate())) {
+                            $emails = (array)$abook->get_col_values('email', $member, true);
+                            if (!empty($emails) && ($email = array_shift($emails))) {
+                                $result['members'][] = array(
+                                    'email' => $email,
+                                    'name' => rcube_addressbook::compose_list_name($member),
+                                );
+                            }
+                        }
+
+                        break 2;
+                    }
+                }
+            }
+        }
+
+        $this->rc->output->command('plugin.expand_attendee_callback', $result);
+    }
+
+
     /*********  Static utility functions  *********/
 
     /**
diff --git a/plugins/libcalendaring/localization/en_US.inc b/plugins/libcalendaring/localization/en_US.inc
index 5ad34ed..82fb7a8 100644
--- a/plugins/libcalendaring/localization/en_US.inc
+++ b/plugins/libcalendaring/localization/en_US.inc
@@ -140,3 +140,9 @@ $labels['declinedeleteconfirm'] = 'Do you also want to delete this declined obje
 
 $labels['savingdata'] = 'Saving data...';
 
+// attendees labels
+$labels['expandattendeegroup'] = 'Substitute with group members';
+$labels['expandattendeegroupnodata'] = 'Unable to substitute this group. No members found.';
+$labels['expandattendeegrouperror'] = 'Unable to substitute this group. It might contain too many members.';
+$labels['expandattendeegroupsizelimit'] = 'This group contains too many members for substituting.';
+
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index 0b2ed3d..0ffaf96 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -918,6 +918,7 @@ a.morelink:hover {
 	white-space: nowrap;
 	overflow: hidden;
 	text-overflow: ellipsis;
+	position: relative;
 }
 
 #taskedit .edit-attendees-table td.name select {
@@ -933,6 +934,14 @@ a.morelink:hover {
 	text-indent: 1000px;
 }
 
+#taskedit .edit-attendees-table a.expandlink {
+	position: absolute;
+	top: 4px;
+	right: 6px;
+	width: 16px;
+	height: 16px;
+}
+
 #edit-attendees-form {
 	position: relative;
 	margin-top: 15px;
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index 5e0dc8e..4c07937 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -615,22 +615,22 @@ function rcube_tasklist_ui(settings)
         };
       }
       rcmail.init_address_input_events($('#edit-attendee-name'), ac_props);
-      rcmail.addEventListener('autocomplete_insert', function(e){
-        if (e.field.name == 'participant') {
-          $('#edit-attendee-add').click();
-        }
-//        else if (e.field.name == 'resource' && e.data && e.data.email) {
-//          add_attendee($.extend(e.data, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'RESOURCE' }));
-//          e.field.value = '';
-//        }
+      rcmail.addEventListener('autocomplete_insert', function(e) {
+          var success = false;
+          if (e.field.name == 'participant') {
+              success = add_attendees(e.insert, { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:(e.data && e.data.type == 'group' ? 'GROUP' : 'INDIVIDUAL') });
+          }
+          if (e.field && success) {
+              e.field.value = '';
+          }
       });
 
-      $('#edit-attendee-add').click(function(){
-        var input = $('#edit-attendee-name');
-        rcmail.ksearch_blur();
-        if (add_attendees(input.val(), { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'INDIVIDUAL' })) {
-          input.val('');
-        }
+      $('#edit-attendee-add').click(function() {
+          var input = $('#edit-attendee-name');
+          rcmail.ksearch_blur();
+          if (add_attendees(input.val(), { role:'REQ-PARTICIPANT', status:'NEEDS-ACTION', cutype:'INDIVIDUAL' })) {
+              input.val('');
+          }
       });
 
       // handle change of "send invitations" checkbox
@@ -1595,7 +1595,7 @@ function rcube_tasklist_ui(settings)
     };
 
     // add the given attendee to the list
-    var add_attendee = function(data, readonly)
+    var add_attendee = function(data, readonly, before)
     {
         if (!me.selected_task)
             return false;
@@ -1624,6 +1624,12 @@ function rcube_tasklist_ui(settings)
         else if (data['delegated-from'])
             tooltip = rcmail.gettext('delegatedfrom', 'tasklist') + data['delegated-from'];
 
+        // add expand button for groups
+        if (data.cutype == 'GROUP') {
+            dispname += ' <a href="#expand" data-email="' + Q(data.email) + '" class="iconbutton add expandlink" title="' + rcmail.gettext('expandattendeegroup','libcalendaring') + '">' +
+                rcmail.gettext('expandattendeegroup','libcalendaring') + '</a>';
+        }
+
         var html = '<td class="name">' + dispname + '</td>' +
             '<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '" title="' + Q(tooltip) + '">' + Q(data.status || '') + '</span></td>' +
             (data.cutype != 'RESOURCE' ? '<td class="sendmail">' + (readonly || !invbox ? '' : invbox) + '</td>' : '') +
@@ -1631,11 +1637,16 @@ function rcube_tasklist_ui(settings)
 
         var tr = $('<tr>')
             .addClass(String(data.role).toLowerCase())
-            .html(html)
-            .appendTo(attendees_list);
+            .html(html);
+
+        if (before)
+            tr.insertBefore(before)
+        else
+            tr.appendTo(attendees_list);
 
         tr.find('a.deletelink').click({ id:(data.email || data.name) }, function(e) { remove_attendee(this, e.data.id); return false; });
         tr.find('a.mailtolink').click(task_attendee_click);
+        tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); });
         tr.find('input.edit-attendee-reply').click(function() {
             var enabled = $('#edit-attendees-invite:checked').length || $('input.edit-attendee-reply:checked').length;
             $('p.attendees-commentbox')[enabled ? 'show' : 'hide']();
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 7894b10..a573128 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -1147,7 +1147,7 @@ class tasklist extends rcube_plugin
         $this->rc->output->set_env('autocomplete_threads', (int)$this->rc->config->get('autocomplete_threads', 0));
         $this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15));
         $this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length'));
-        $this->rc->output->add_label('autocompletechars', 'autocompletemore');
+        $this->rc->output->add_label('autocompletechars', 'autocompletemore', 'libcalendaring.expandattendeegroup', 'libcalendaring.expandattendeegroupnodata');
 
         $this->rc->output->set_pagetitle($this->gettext('navtitle'));
         $this->rc->output->send('tasklist.mainview');


commit 0747f9f95dbe245f63b85f55328377d2565b6839
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 19 09:37:13 2014 +0200

    Fix autocomplete response after request identifier changed in Roundcube core

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 402d15b..840a2ed 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -2080,7 +2080,7 @@ class calendar extends rcube_plugin
   public function resources_autocomplete()
   {
     $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC, true);
-    $sid    = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
+    $sid    = rcube_utils::get_input_value('_reqid', rcube_utils::INPUT_GPC);
     $maxnum = (int)$this->rc->config->get('autocomplete_max', 15);
     $results = array();
 


commit 3aab910ae1e379bae7f1913ae7ede5a564e2a829
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 19 09:27:36 2014 +0200

    Add icons for resource autocomplete list (#3415)

diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 1972dce..85a7aa5 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -1298,6 +1298,20 @@ td.topalign {
 	display: block;
 }
 
+#eventedit .ui-tabs-panel {
+	min-height: 24em;
+}
+
+#rcmKSearchpane ul li.resource i.icon,
+#rcmKSearchpane ul li.collection i.icon {
+	background-image: url(images/autocomplete.png);
+	background-position: -1px -2px;
+}
+
+#rcmKSearchpane ul li.collection i.icon {
+	background-position: -1px -26px;
+}
+
 a.dropdown-link {
 	font-size: 11px;
 	text-decoration: none;
@@ -1309,10 +1323,6 @@ a.dropdown-link:after {
 	color: #666;
 }
 
-#eventedit .ui-tabs-panel {
-	min-height: 24em;
-}
-
 .ui-dialog-buttonset a.dropdown-link {
 	position: relative;
 	top: 2px;
diff --git a/plugins/calendar/skins/larry/images/autocomplete.png b/plugins/calendar/skins/larry/images/autocomplete.png
new file mode 100644
index 0000000..593c007
Binary files /dev/null and b/plugins/calendar/skins/larry/images/autocomplete.png differ


commit e6e5c0e17a33a30edbdfec4e47aac19a626ba4fa
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Mon Aug 18 18:07:57 2014 +0200

    Don't override attendees table styles from calendar

diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index 824f605..0b2ed3d 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -860,45 +860,45 @@ a.morelink:hover {
 	border-bottom: 2px solid #fafafa;
 }
 
-.edit-attendees-table {
+#taskedit .edit-attendees-table {
 	width: 100%;
 	margin-top: 0.5em;
 }
 
-.edit-attendees-table tbody td {
+#taskedit .edit-attendees-table tbody td {
 	padding: 4px 7px;
 }
 
-.edit-attendees-table tbody tr:last-child td {
+#taskedit .edit-attendees-table tbody tr:last-child td {
 	border-bottom: 0;
 }
 
-.edit-attendees-table th.role,
-.edit-attendees-table td.role {
+#taskedit .edit-attendees-table th.role,
+#taskedit .edit-attendees-table td.role {
 	width: 9em;
 }
 
-.edit-attendees-table th.availability,
-.edit-attendees-table td.availability,
-.edit-attendees-table th.confirmstate,
-.edit-attendees-table td.confirmstate {
+#taskedit .edit-attendees-table th.availability,
+#taskedit .edit-attendees-table td.availability,
+#taskedit .edit-attendees-table th.confirmstate,
+#taskedit .edit-attendees-table td.confirmstate {
 	width: 6em;
 }
 
-.edit-attendees-table th.options,
-.edit-attendees-table td.options {
+#taskedit .edit-attendees-table th.options,
+#taskedit .edit-attendees-table td.options {
 	width: 24px;
 	padding: 2px 4px;
 	text-align: right;
 }
 
-.edit-attendees-table th.sendmail,
-.edit-attendees-table td.sendmail {
+#taskedit .edit-attendees-table th.sendmail,
+#taskedit .edit-attendees-table td.sendmail {
 	width: 48px;
 	padding: 2px;
 }
 
-.edit-attendees-table th.sendmail label {
+#taskedit .edit-attendees-table th.sendmail label {
 	display: inline-block;
 	position: relative;
 	top: 4px;
@@ -912,19 +912,19 @@ a.morelink:hover {
 	background: url(images/sendinvitation.png) 1px 0 no-repeat;
 }
 
-.edit-attendees-table th.name,
-.edit-attendees-table td.name {
+#taskedit .edit-attendees-table th.name,
+#taskedit .edit-attendees-table td.name {
 	width: auto;
 	white-space: nowrap;
 	overflow: hidden;
 	text-overflow: ellipsis;
 }
 
-.edit-attendees-table td.name select {
+#taskedit .edit-attendees-table td.name select {
 	width: 100%;
 }
 
-.edit-attendees-table a.deletelink {
+#taskedit .edit-attendees-table a.deletelink {
 	display: inline-block;
 	width: 17px;
 	height: 17px;




More information about the commits mailing list