plugins/calendar plugins/libcalendaring plugins/tasklist

Thomas Brüderli bruederli at kolabsys.com
Wed Aug 27 14:01:38 CEST 2014


 plugins/calendar/calendar.php                      |   17 +++++-
 plugins/calendar/calendar_ui.js                    |   52 +++++++++++----------
 plugins/calendar/config.inc.php.dist               |   23 ++++++---
 plugins/calendar/lib/calendar_ui.php               |   12 +++-
 plugins/calendar/skins/classic/calendar.css        |    6 +-
 plugins/calendar/skins/larry/calendar.css          |    6 +-
 plugins/libcalendaring/lib/libcalendaring_itip.php |   16 ++++--
 plugins/libcalendaring/libcalendaring.js           |    2 
 plugins/libcalendaring/skins/larry/libcal.css      |    5 +-
 plugins/tasklist/skins/larry/tasklist.css          |    6 +-
 plugins/tasklist/tasklist.js                       |   46 +++++++++++-------
 plugins/tasklist/tasklist.php                      |   10 +++-
 plugins/tasklist/tasklist_ui.php                   |   10 +++-
 13 files changed, 138 insertions(+), 73 deletions(-)

New commits:
commit ed6eaac9d09a0135bb41bdfc45822f64b5afd9ee
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Aug 27 14:00:08 2014 +0200

    Add config option to hide iTip sending checkboxes or even disable it entirely (#3483).
    
    The default setting remains visible + checked. Set
    
      $config['calendar_itip_send_option'] = 1;
    
    to hide the checkboxes and implicitly send iTip notifications.

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 36947ea..e26c6db 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -54,6 +54,7 @@ class calendar extends rcube_plugin
     'calendar_event_coloring'  => 0,
     'calendar_time_indicator'  => true,
     'calendar_allow_invite_shared' => false,
+    'calendar_itip_send_option'    => 3,
     'calendar_itip_after_action'   => 0,
   );
 
@@ -829,7 +830,10 @@ class calendar extends rcube_plugin
     // don't notify if modifying a recurring instance (really?)
     if ($event['_savemode'] && $event['_savemode'] != 'all' && $event['_notify'])
       unset($event['_notify']);
-    
+    // force notify if hidden + active
+    else if ((int)$this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']) === 1)
+      $event['_notify'] = 1;
+
     // read old event data in order to find changes
     if (($event['_notify'] || $event['decline']) && $action != 'new')
       $old = $this->driver->get_event($event);
@@ -933,6 +937,7 @@ class calendar extends rcube_plugin
         break;
 
       case "rsvp":
+        $itip_sending = $this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']);
         $status = get_input_value('status', RCUBE_INPUT_GPC);
         $reply_comment = $event['comment'];
         $ev = $this->driver->get_event($event);
@@ -940,7 +945,7 @@ class calendar extends rcube_plugin
         $event = $ev;
 
         if ($success = $this->driver->edit_rsvp($event, $status)) {
-          $noreply = intval(get_input_value('noreply', RCUBE_INPUT_GPC)) || $status == 'needs-action';
+          $noreply = intval(get_input_value('noreply', RCUBE_INPUT_GPC)) || $status == 'needs-action' || $itip_sending === 0;
           $reload = $event['calendar'] != $ev['calendar'] ? 2 : 1;
           $organizer = null;
           $emails = $this->get_user_emails();
@@ -1475,6 +1480,7 @@ class calendar extends rcube_plugin
     $settings['time_indicator'] = (int)$this->rc->config->get('calendar_time_indicator', $this->defaults['calendar_time_indicator']);
     $settings['invite_shared'] = (int)$this->rc->config->get('calendar_allow_invite_shared', $this->defaults['calendar_allow_invite_shared']);
     $settings['invitation_calendars'] = (bool)$this->rc->config->get('kolab_invitation_calendars', false);
+    $settings['itip_notify'] = (int)$this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']);
 
     // get user identity to create default attendee
     if ($this->ui->screen == 'calendar') {
@@ -1771,6 +1777,7 @@ class calendar extends rcube_plugin
 
     $itip = $this->load_itip();
     $emails = $this->get_user_emails();
+    $itip_notify = (int)$this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']);
 
     // add comment to the iTip attachment
     $event['comment'] = $comment;
@@ -1795,7 +1802,7 @@ class calendar extends rcube_plugin
         continue;
 
       // skip if notification is disabled for this attendee
-      if ($attendee['noreply'])
+      if ($attendee['noreply'] && $itip_notify & 2)
         continue;
       
       // which template to use for mail text
@@ -2391,12 +2398,14 @@ class calendar extends rcube_plugin
    */
   public function mail_import_itip()
   {
+    $itip_sending = $this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']);
+
     $uid     = get_input_value('_uid', RCUBE_INPUT_POST);
     $mbox    = get_input_value('_mbox', RCUBE_INPUT_POST);
     $mime_id = get_input_value('_part', RCUBE_INPUT_POST);
     $status  = get_input_value('_status', RCUBE_INPUT_POST);
     $delete  = intval(get_input_value('_del', RCUBE_INPUT_POST));
-    $noreply = intval(get_input_value('_noreply', RCUBE_INPUT_POST)) || $status == 'needs-action';
+    $noreply = intval(get_input_value('_noreply', RCUBE_INPUT_POST)) || $status == 'needs-action' || $itip_sending === 0;
 
     $error_msg = $this->gettext('errorimportingevent');
     $success = false;
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index a9c47e6..e7bdfa7 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -688,8 +688,8 @@ function rcube_calendar_ui(settings)
       var invite = $('#edit-attendees-invite').get(0);
       var comment = $('#edit-attendees-comment');
 
-      notify.checked = has_attendees(event);
-      invite.checked = true;
+      invite.checked = settings.itip_notify & 1 > 0;
+      notify.checked = has_attendees(event) && invite.checked;
 
       if (event.allDay) {
         starttime.val("12:00").hide();
@@ -726,7 +726,7 @@ function rcube_calendar_ui(settings)
       event_attendees = [];
       attendees_list = $('#edit-attendees-table > tbody').html('');
       resources_list = $('#edit-resources-table > tbody').html('');
-      $('#edit-attendees-notify')[(notify.checked && allow_invitations ? 'show' : 'hide')]();
+      $('#edit-attendees-notify')[(allow_invitations && (settings.itip_notify & 2) ? 'show' : 'hide')]();
       $('#edit-localchanges-warning')[(has_attendees(event) && !(allow_invitations || (calendar.owner && is_organizer(event, calendar.owner))) ? 'show' : 'hide')]();
 
       var load_attendees_tab = function()
@@ -743,8 +743,7 @@ function rcube_calendar_ui(settings)
 
         // make sure comment box is visible if at least one attendee has reply enabled
         // or global "send invitations" checkbox is checked
-        if (reply_selected || $('#edit-attendees-invite:checked').length)
-          $('p.attendees-commentbox').show();
+        $('#eventedit .attendees-commentbox')[(reply_selected || invite.checked ? 'show' : 'hide')]();
 
         // select the correct organizer identity
         var identity_id = 0;
@@ -840,7 +839,7 @@ function rcube_calendar_ui(settings)
                 need_invitation = true;
                 delete data.attendees[i]['noreply'];
               }
-              else {
+              else if (settings.itip_notify > 0) {
                 data.attendees[i].noreply = 1;
               }
             }
@@ -849,7 +848,7 @@ function rcube_calendar_ui(settings)
 
         // tell server to send notifications
         if ((data.attendees.length || (event.id && event.attendees.length)) && allow_invitations && (notify.checked || invite.checked || need_invitation)) {
-          data._notify = 1;
+          data._notify = settings.itip_notify;
           data._comment = comment.val();
         }
 
@@ -1924,7 +1923,7 @@ function rcube_calendar_ui(settings)
 
       // send invitation checkbox
       var invbox = '<input type="checkbox" class="edit-attendee-reply" value="' + Q(data.email) +'" title="' + Q(rcmail.gettext('calendar.sendinvitations')) + '" '
-        + (!data.noreply ? 'checked="checked" ' : '') + '/>';
+        + (!data.noreply && settings.itip_notify & 1 ? 'checked="checked" ' : '') + '/>';
 
       if (data['delegated-to'])
         tooltip = rcmail.gettext('delegatedto', 'calendar') + data['delegated-to'];
@@ -1941,7 +1940,7 @@ function rcube_calendar_ui(settings)
         '<td class="name">' + dispname + '</td>' +
         '<td class="availability"><img src="./program/resources/blank.gif" class="availabilityicon ' + avail + '" data-email="' + data.email + '" alt="" /></td>' +
         '<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '" title="' + Q(tooltip) + '">' + Q(data.status || '') + '</span></td>' +
-        (data.cutype != 'RESOURCE' ? '<td class="sendmail">' + (organizer || readonly || !invbox ? '' : invbox) + '</td>' : '') +
+        (data.cutype != 'RESOURCE' ? '<td class="invite">' + (organizer || readonly || !invbox ? '' : invbox) + '</td>' : '') +
         '<td class="options">' + (organizer || readonly ? '' : dellink) + '</td>';
 
       var table = rcmail.env.calendar_resources && data.cutype == 'RESOURCE' ? resources_list : attendees_list;
@@ -1959,7 +1958,7 @@ function rcube_calendar_ui(settings)
       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']();
+        $('#eventedit .attendees-commentbox')[enabled ? 'show' : 'hide']();
       });
 
       // select organizer identity
@@ -2338,7 +2337,7 @@ function rcube_calendar_ui(settings)
 
         // submit status change to server
         var submit_data = $.extend({}, me.selected_event, { source:null, comment:$('#reply-comment-event-rsvp').val() }),
-          noreply = $('#noreply-event-rsvp').prop('checked') ? 1 : 0;
+          noreply = $('#noreply-event-rsvp:checked').length ? 1 : 0;
 
         if (settings.invitation_calendars) {
           update_event('rsvp', submit_data, { status:response, noreply:noreply });
@@ -2431,17 +2430,23 @@ function rcube_calendar_ui(settings)
       
       // event has attendees, ask whether to notify them
       if (has_attendees(event)) {
+        var checked = (settings.itip_notify & 1 ? ' checked="checked"' : '');
         if (is_organizer(event)) {
           notify = true;
-          html += '<div class="message">' +
-            '<label><input class="confirm-attendees-donotify" type="checkbox" checked="checked" value="1" name="notify" /> ' +
-            rcmail.gettext((action == 'remove' ? 'sendcancellation' : 'sendnotifications'), 'calendar') + 
-            '</label></div>';
+          if (settings.itip_notify & 2) {
+            html += '<div class="message">' +
+              '<label><input class="confirm-attendees-donotify" type="checkbox"' + checked + ' value="1" name="notify" /> ' +
+                rcmail.gettext((action == 'remove' ? 'sendcancellation' : 'sendnotifications'), 'calendar') + 
+              '</label></div>';
+          }
+          else {
+            data._notify = settings.itip_notify;
+          }
         }
         else if (action == 'remove' && is_attendee(event)) {
           decline = true;
           html += '<div class="message">' +
-            '<label><input class="confirm-attendees-decline" type="checkbox" checked="checked" value="1" name="decline" /> ' +
+            '<label><input class="confirm-attendees-decline" type="checkbox"' + checked + ' value="1" name="decline" /> ' +
             rcmail.gettext('itipdeclineevent', 'calendar') + 
             '</label></div>';
         }
@@ -2466,14 +2471,15 @@ function rcube_calendar_ui(settings)
       if (html) {
         var $dialog = $('<div>').html(html);
       
-        $dialog.find('a.button').button().click(function(e){
+        $dialog.find('a.button').button().click(function(e) {
           data._savemode = String(this.href).replace(/.+#/, '');
-          if ($dialog.find('input.confirm-attendees-donotify').get(0))
-            data._notify = notify && $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0;
-          if (decline && $dialog.find('input.confirm-attendees-decline:checked'))
+          data._notify = settings.itip_notify;
+          if ($dialog.find('input.confirm-attendees-donotify').length)
+            data._notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0;
+          if (decline && $dialog.find('input.confirm-attendees-decline:checked').length)
             data.decline = 1;
           update_event(action, data);
-          $dialog.dialog("destroy").hide();
+          $dialog.dialog("close");
           return false;
         });
         
@@ -2483,7 +2489,7 @@ function rcube_calendar_ui(settings)
           buttons.push({
             text: rcmail.gettext((action == 'remove' ? 'remove' : 'save'), 'calendar'),
             click: function() {
-              data._notify = notify && $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0;
+              data._notify = notify && $dialog.find('input.confirm-attendees-donotify:checked').length ? 1 : 0;
               data.decline = decline && $dialog.find('input.confirm-attendees-decline:checked').length ? 1 : 0;
               update_event(action, data);
               $(this).dialog("close");
@@ -3809,7 +3815,7 @@ function rcube_calendar_ui(settings)
       $('#edit-attendees-invite').change(function() {
         $('#edit-attendees-donotify,input.edit-attendee-reply').prop('checked', this.checked);
         // hide/show comment field
-        $('.attendees-commentbox')[this.checked ? 'show' : 'hide']();
+        $('#eventedit .attendees-commentbox')[this.checked ? 'show' : 'hide']();
       });
 
       // delegate change event to "send invitations" checkbox
diff --git a/plugins/calendar/config.inc.php.dist b/plugins/calendar/config.inc.php.dist
index 5ac25f6..32e1c74 100644
--- a/plugins/calendar/config.inc.php.dist
+++ b/plugins/calendar/config.inc.php.dist
@@ -113,6 +113,21 @@ $config['calendar_allow_invite_shared'] = false;
 // this can be the case if invitations are sent to mailing lists or alias email addresses.
 $config['calendar_allow_itip_uninvited'] = true;
 
+// controls the visibility/default of the checkbox controlling the sending of iTip invitations
+// 0 = hidden  + disabled
+// 1 = hidden  + active
+// 2 = visible + unchecked
+// 3 = visible + active
+$config['calendar_itip_send_option'] = 3;
+
+// Action taken after iTip request is handled. Possible values:
+// 0 - no action
+// 1 - move to Trash
+// 2 - delete the message
+// 3 - flag as deleted
+// folder_name - move the message to the specified folder
+$config['calendar_itip_after_action'] = 0;
+
 // enable asynchronous free-busy triggering after data changed
 $config['calendar_freebusy_trigger'] = false;
 
@@ -145,12 +160,4 @@ $config['kolab_invitation_calendars'] = true;
 // LDAP directory configuration to find avilable resources for events
 // $config['calendar_resources_directory'] = array(/* ldap_public-like address book configuration */);
 
-// Action taken after iTip request is handled. Possible values:
-// 0 - no action
-// 1 - move to Trash
-// 2 - delete the message
-// 3 - flag as deleted
-// folder_name - move the message to the specified folder
-$config['calendar_itip_after_action'] = 0;
-
 ?>
diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php
index 291f365..e66e5f8 100644
--- a/plugins/calendar/lib/calendar_ui.php
+++ b/plugins/calendar/lib/calendar_ui.php
@@ -2,12 +2,11 @@
 /**
  * User Interface class for the Calendar plugin
  *
- * @version @package_version@
  * @author Lazlo Westerhof <hello at lazlo.me>
  * @author Thomas Bruederli <bruederli at kolabsys.com>
  *
  * Copyright (C) 2010, Lazlo Westerhof <hello at lazlo.me>
- * Copyright (C) 2012, Kolab Systems AG <contact at kolabsys.com>
+ * Copyright (C) 2014, Kolab Systems AG <contact at kolabsys.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -706,11 +705,18 @@ class calendar_ui
     $table->add_header('availability', $this->cal->gettext('availability'));
     $table->add_header('confirmstate', $this->cal->gettext('confirmstate'));
     if ($invitations) {
-      $table->add_header(array('class' => 'sendmail', 'title' => $this->cal->gettext('sendinvitations')),
+      $table->add_header(array('class' => 'invite', 'title' => $this->cal->gettext('sendinvitations')),
         $invite->show(1) . html::label('edit-attendees-invite', $this->cal->gettext('sendinvitations')));
     }
     $table->add_header('options', '');
 
+    // hide invite column if disabled by config
+    $itip_notify = (int)$this->rc->config->get('calendar_itip_send_option', $this->cal->defaults['calendar_itip_send_option']);
+    if ($invitations && !($itip_notify & 2)) {
+        $css = sprintf('#%s td.invite, #%s th.invite { display:none !important }', $attrib['id'], $attrib['id']);
+        $this->rc->output->add_footer(html::tag('style', array('type' => 'text/css'), $css));
+    }
+
     return $table->show($attrib);
   }
 
diff --git a/plugins/calendar/skins/classic/calendar.css b/plugins/calendar/skins/classic/calendar.css
index 3e78900..a4371bf 100644
--- a/plugins/calendar/skins/classic/calendar.css
+++ b/plugins/calendar/skins/classic/calendar.css
@@ -836,8 +836,8 @@ td.topalign {
 	padding-right: 4px;
 }
 
-.edit-attendees-table th.sendmail,
-.edit-attendees-table td.sendmail {
+.edit-attendees-table th.invite,
+.edit-attendees-table td.invite {
 	width: 24px;
 	padding: 2px;
 	white-space: nowrap;
@@ -845,7 +845,7 @@ td.topalign {
 	text-overflow: hidden;
 }
 
-#eventedit .edit-attendees-table th.sendmail label {
+#eventedit .edit-attendees-table th.invite label {
 	display: none;
 }
 
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 0700455..17efff5 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -978,13 +978,13 @@ td.topalign {
 	padding: 2px 4px;
 }
 
-#eventedit .edit-attendees-table th.sendmail,
-#eventedit .edit-attendees-table td.sendmail {
+#eventedit .edit-attendees-table th.invite,
+#eventedit .edit-attendees-table td.invite {
 	width: 44px;
 	padding: 2px;
 }
 
-#eventedit .edit-attendees-table th.sendmail label {
+#eventedit .edit-attendees-table th.invite label {
 	display: inline-block;
 	position: relative;
 	top: 4px;
diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php
index 6ff1229..ce68655 100644
--- a/plugins/libcalendaring/lib/libcalendaring_itip.php
+++ b/plugins/libcalendaring/lib/libcalendaring_itip.php
@@ -563,11 +563,19 @@ class libcalendaring_itip
      */
     public function itip_rsvp_options_ui($dom_id, $disable = false)
     {
+        $itip_sending = $this->rc->config->get('calendar_itip_send_option', 3);
+
+        // itip sending is entirely disabled
+        if ($itip_sending === 0) {
+            return '';
+        }
         // add checkbox to suppress itip reply message
-        $rsvp_additions = html::label(array('class' => 'noreply-toggle'),
-            html::tag('input', array('type' => 'checkbox', 'id' => 'noreply-'.$dom_id, 'value' => 1, 'disabled' => $disable))
-            . ' ' . $this->gettext('itipsuppressreply')
-        );
+        else if ($itip_sending >= 2) {
+            $rsvp_additions = html::label(array('class' => 'noreply-toggle'),
+                html::tag('input', array('type' => 'checkbox', 'id' => 'noreply-'.$dom_id, 'value' => 1, 'disabled' => $disable, 'checked' => ($itip_sending & 1) == 0))
+                . ' ' . $this->gettext('itipsuppressreply')
+            );
+        }
 
         // add input field for reply comment
         $rsvp_additions .= html::a(array('href' => '#toggle', 'class' => 'reply-comment-toggle'), $this->gettext('itipeditresponse'));
diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index 39b34ae..cd06827 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -805,7 +805,7 @@ rcube_libcalendaring.add_from_itip_mail = function(mime_id, task, status, dom_id
 
     var noreply = 0, comment = '';
     if (dom_id) {
-      noreply = $('#noreply-'+dom_id).prop('checked') ? 1 : 0;
+      noreply = $('#noreply-'+dom_id+':checked').length ? 1 : 0;
       if (!noreply)
         comment = $('#reply-comment-'+dom_id).val();
     }
diff --git a/plugins/libcalendaring/skins/larry/libcal.css b/plugins/libcalendaring/skins/larry/libcal.css
index 7cfe630..89e123f 100644
--- a/plugins/libcalendaring/skins/larry/libcal.css
+++ b/plugins/libcalendaring/skins/larry/libcal.css
@@ -59,10 +59,13 @@ span.edit-alarm-set {
 
 a.reply-comment-toggle {
 	display: inline-block;
-	margin-left: 1em;
 	color: #666;
 }
 
+label.noreply-toggle + a.reply-comment-toggle {
+	margin-left: 1em;
+}
+
 .itip-reply-comment textarea {
 	display: block;
 	width: 90%;
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index 0ffaf96..026067c 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -892,13 +892,13 @@ a.morelink:hover {
 	text-align: right;
 }
 
-#taskedit .edit-attendees-table th.sendmail,
-#taskedit .edit-attendees-table td.sendmail {
+#taskedit .edit-attendees-table th.invite,
+#taskedit .edit-attendees-table td.invite {
 	width: 48px;
 	padding: 2px;
 }
 
-#taskedit .edit-attendees-table th.sendmail label {
+#taskedit .edit-attendees-table th.invite label {
 	display: inline-block;
 	position: relative;
 	top: 4px;
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index 6b88867..82dd9c4 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -542,7 +542,7 @@ function rcube_tasklist_ui(settings)
                     t: me.selected_task,
                     filter: filtermask,
                     status: response,
-                    noreply: $('#noreply-task-rsvp').prop('checked') ? 1 : 0,
+                    noreply: $('#noreply-task-rsvp:checked').length ? 1 : 0,
                     comment: $('#reply-comment-task-rsvp').val()
                 });
 
@@ -637,7 +637,7 @@ function rcube_tasklist_ui(settings)
       $('#edit-attendees-invite').change(function() {
         $('#edit-attendees-donotify,input.edit-attendee-reply').prop('checked', this.checked);
         // hide/show comment field
-        $('.attendees-commentbox')[this.checked ? 'show' : 'hide']();
+        $('#taskeditform .attendees-commentbox')[this.checked ? 'show' : 'hide']();
       });
 
       // delegate change task to "send invitations" checkbox
@@ -1076,17 +1076,28 @@ function rcube_tasklist_ui(settings)
     var save_task_confirm = function(rec, action, updates)
     {
         var data = $.extend({}, rec, updates || {}),
-          notify = false, partstat = false, html = '';
+          notify = false, partstat = false, html = '',
+          do_confirm = settings.itip_notify & 2;
 
         // task has attendees, ask whether to notify them
         if (has_attendees(rec) && is_organizer(rec)) {
             notify = true;
-            html = rcmail.gettext('changeconfirmnotifications', 'tasklist');
+            if (do_confirm) {
+                html = rcmail.gettext('changeconfirmnotifications', 'tasklist');
+            }
+            else {
+                data._notify = settings.itip_notify;
+            }
         }
         // ask whether to change my partstat and notify organizer
         else if (data._status_before !== undefined && data.status && data._status_before != data.status && is_attendee(rec)) {
           partstat = true;
-          html = rcmail.gettext('partstatupdatenotification', 'tasklist');
+          if (do_confirm) {
+              html = rcmail.gettext('partstatupdatenotification', 'tasklist');
+          }
+          else if (settings.itip_notify & 1) {
+              data._reportpartstat = data.status == 'CANCELLED' ? 'DECLINED' : data.status;
+          }
         }
 
         // remove to avoid endless recursion
@@ -1622,7 +1633,7 @@ function rcube_tasklist_ui(settings)
 
         // send invitation checkbox
         var invbox = '<input type="checkbox" class="edit-attendee-reply" value="' + Q(data.email) +'" title="' + Q(rcmail.gettext('tasklist.sendinvitations')) + '" '
-            + (!data.noreply ? 'checked="checked" ' : '') + '/>';
+            + (!data.noreply && settings.itip_notify & 1 ? 'checked="checked" ' : '') + '/>';
 
         if (data['delegated-to'])
             tooltip = rcmail.gettext('delegatedto', 'tasklist') + data['delegated-to'];
@@ -1637,7 +1648,7 @@ function rcube_tasklist_ui(settings)
 
         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>' : '') +
+            (data.cutype != 'RESOURCE' ? '<td class="invite">' + (readonly || !invbox ? '' : invbox) + '</td>' : '') +
             '<td class="options">' + (readonly ? '' : dellink) + '</td>';
 
         var tr = $('<tr>')
@@ -1654,7 +1665,7 @@ function rcube_tasklist_ui(settings)
         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']();
+            $('#taskeditform .attendees-commentbox')[enabled ? 'show' : 'hide']();
         });
 
         task_attendees.push(data);
@@ -1940,8 +1951,8 @@ function rcube_tasklist_ui(settings)
         var invite = $('#edit-attendees-invite').get(0);
         var comment = $('#edit-attendees-comment');
 
-        notify.checked = has_attendees(rec);
-        invite.checked = true;
+        invite.checked = settings.itip_notify & 1 > 0;
+        notify.checked = has_attendees(rec) && invite.checked;
 
         // tag-edit line
         var tagline = $(rcmail.gui_objects.edittagline).empty();
@@ -1974,7 +1985,7 @@ function rcube_tasklist_ui(settings)
 
         task_attendees = [];
         attendees_list = $('#edit-attendees-table > tbody').html('');
-        $('#edit-attendees-notify')[(notify.checked && allow_invitations ? 'show' : 'hide')]();
+        $('#edit-attendees-notify')[(allow_invitations && (settings.itip_notify & 2) ? 'show' : 'hide')]();
         $('#edit-localchanges-warning')[(has_attendees(rec) && !(allow_invitations || (rec.owner && is_organizer(rec, rec.owner))) ? 'show' : 'hide')]();
 
         // attendees (aka assignees)
@@ -1992,14 +2003,12 @@ function rcube_tasklist_ui(settings)
 
             // make sure comment box is visible if at least one attendee has reply enabled
             // or global "send invitations" checkbox is checked
-            if (reply_selected || $('#edit-attendees-invite:checked').length) {
-                $('p.attendees-commentbox').show();
-            }
+            $('#taskeditform .attendees-commentbox')[(reply_selected || invite.checked ? 'show' : 'hide')]();
 
             // select the correct organizer identity
             var identity_id = 0;
             $.each(settings.identities, function(i,v) {
-                if (rec.organizer && v == rec.organizer.email) {
+                if (!rec.organizer || v == rec.organizer.email) {
                     identity_id = i;
                     return false;
                 }
@@ -2112,7 +2121,7 @@ function rcube_tasklist_ui(settings)
                             need_invitation = true;
                             delete data.attendees[i]['noreply'];
                         }
-                        else {
+                        else if (settings.itip_notify > 0) {
                             data.attendees[i].noreply = 1;
                         }
                     }
@@ -2121,9 +2130,12 @@ function rcube_tasklist_ui(settings)
 
             // tell server to send notifications
             if ((data.attendees.length || (rec.id && rec.attendees.length)) && allow_invitations && (notify.checked || invite.checked || need_invitation)) {
-                data._notify = 1;
+                data._notify = settings.itip_notify;
                 data._comment = comment.val();
             }
+            else if (data._notify) {
+                delete data._notify;
+            }
 
             if (save_task(data, action))
                 $dialog.dialog('close');
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index fe8c5c3..fb88139 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -203,6 +203,10 @@ class tasklist extends rcube_plugin
         $oldrec = $rec;
         $success = $refresh = false;
 
+        // force notify if hidden + active
+        if ((int)$this->rc->config->get('calendar_itip_send_option', 3) === 1 && empty($rec['_reportpartstat']))
+            $rec['_notify'] = 1;
+
         switch ($action) {
         case 'new':
             $oldrec = null;
@@ -575,7 +579,8 @@ class tasklist extends rcube_plugin
         }
 
         // set organizer from identity selector
-        if (isset($rec['_identity']) && ($identity = $this->rc->user->get_identity($rec['_identity']))) {
+        if ((isset($rec['_identity']) || (!empty($rec['attendees']) && empty($rec['organizer']))) &&
+                ($identity = $this->rc->user->get_identity($rec['_identity']))) {
             $rec['organizer'] = array('name' => $identity['name'], 'email' => $identity['email']);
         }
 
@@ -696,6 +701,7 @@ class tasklist extends rcube_plugin
 
         $itip   = $this->load_itip();
         $emails = $this->lib->get_user_emails();
+        $itip_notify = (int)$this->rc->config->get('calendar_itip_send_option', 3);
 
         // add comment to the iTip attachment
         $task['comment'] = $comment;
@@ -725,7 +731,7 @@ class tasklist extends rcube_plugin
             }
 
             // skip if notification is disabled for this attendee
-            if ($attendee['noreply']) {
+            if ($attendee['noreply'] && $itip_notify & 2) {
                 continue;
             }
 
diff --git a/plugins/tasklist/tasklist_ui.php b/plugins/tasklist/tasklist_ui.php
index f3a2bb6..8d4170a 100644
--- a/plugins/tasklist/tasklist_ui.php
+++ b/plugins/tasklist/tasklist_ui.php
@@ -72,6 +72,7 @@ class tasklist_ui
         $settings = array();
 
         $settings['invite_shared'] = (int)$this->rc->config->get('calendar_allow_invite_shared', 0);
+        $settings['itip_notify']   = (int)$this->rc->config->get('calendar_itip_send_option', 3);
         $settings['sort_col']      = $this->rc->config->get('tasklist_sort_col', '');
         $settings['sort_order']    = $this->rc->config->get('tasklist_sort_order', 'asc');
 
@@ -450,11 +451,18 @@ class tasklist_ui
         $table->add_header('name', $this->plugin->gettext($attrib['coltitle'] ?: 'attendee'));
         $table->add_header('confirmstate', $this->plugin->gettext('confirmstate'));
         if ($invitations) {
-            $table->add_header(array('class' => 'sendmail', 'title' => $this->plugin->gettext('sendinvitations')),
+            $table->add_header(array('class' => 'invite', 'title' => $this->plugin->gettext('sendinvitations')),
                 $invite->show(1) . html::label('edit-attendees-invite', $this->plugin->gettext('sendinvitations')));
         }
         $table->add_header('options', '');
 
+        // hide invite column if disabled by config
+        $itip_notify = (int)$this->rc->config->get('calendar_itip_send_option', 3);
+        if ($invitations && !($itip_notify & 2)) {
+            $css = sprintf('#%s td.invite, #%s th.invite { display:none !important }', $attrib['id'], $attrib['id']);
+            $this->rc->output->add_footer(html::tag('style', array('type' => 'text/css'), $css));
+        }
+
         return $table->show($attrib);
     }
 




More information about the commits mailing list