diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index c9e9f676..0c2708d5 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -1644,6 +1644,10 @@ class calendar extends rcube_plugin
// skip myself for obvious reasons
if (!$attendee['email'] || in_array(strtolower($attendee['email']), $emails))
continue;
+
+ // skip if notification is disabled for this attendee
+ if ($attendee['noreply'])
+ continue;
// which template to use for mail text
$is_new = !in_array($attendee['email'], $old_attendees);
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index cc074747..ff741656 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -753,9 +753,24 @@ function rcube_calendar_ui(settings)
// don't submit attendees if only myself is added as organizer
if (data.attendees.length == 1 && data.attendees[0].role == 'ORGANIZER' && String(data.attendees[0].email).toLowerCase() == settings.identity.email)
data.attendees = [];
-
+
+ // per-attendee notification suppression
+ var need_invitation = false;
+ if (allow_invitations) {
+ $.each(data.attendees, function (i, v) {
+ if (v.role != 'ORGANIZER') {
+ if ($('input.edit-attendee-reply[value="' + v.email + '"]').prop('checked')) {
+ need_invitation = true;
+ }
+ else {
+ data.attendees[i].noreply = 1;
+ }
+ }
+ });
+ }
+
// tell server to send notifications
- if ((data.attendees.length || (event.id && event.attendees.length)) && allow_invitations && (notify.checked || invite.checked)) {
+ if ((data.attendees.length || (event.id && event.attendees.length)) && allow_invitations && (notify.checked || invite.checked || need_invitation)) {
data._notify = 1;
data._comment = comment.val();
}
@@ -1543,6 +1558,9 @@ function rcube_calendar_ui(settings)
var dellink = '' + icon + '';
var tooltip = data.status || '';
+ // send invitation checkbox
+ var invbox = '';
+
if (data['delegated-to'])
tooltip = rcmail.gettext('delegatedto', 'calendar') + data['delegated-to'];
else if (data['delegated-from'])
@@ -1552,7 +1570,7 @@ function rcube_calendar_ui(settings)
'
' + dispname + ' | ' +
' | ' +
'' + Q(data.status || '') + ' | ' +
- '' + (organizer || readonly ? '' : dellink) + ' | ';
+ '' + (organizer || readonly ? '' : dellink + invbox) + ' | ';
var table = rcmail.env.calendar_resources && data.cutype == 'RESOURCE' ? resources_list : attendees_list;
var tr = $('')
@@ -3368,9 +3386,17 @@ function rcube_calendar_ui(settings)
return false;
});
- // keep these two checkboxes in sync
- $('#edit-attendees-donotify, #edit-attendees-invite').click(function(){
- $('#edit-attendees-donotify, #edit-attendees-invite').prop('checked', this.checked);
+ // handle change of "send invitations" checkbox
+ $('#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']();
+ });
+
+ // delegate change event to "send invitations" checkbox
+ $('#edit-attendees-donotify').change(function() {
+ $('#edit-attendees-invite').click();
+ return false;
});
$('#edit-attendee-schedule').click(function(){
diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php
index bc602388..635ff535 100644
--- a/plugins/calendar/lib/calendar_ui.php
+++ b/plugins/calendar/lib/calendar_ui.php
@@ -714,11 +714,11 @@ class calendar_ui
'rows' => 4, 'cols' => 55, 'title' => $this->cal->gettext('itipcommenttitle')));
return html::div($attrib,
+ html::p('attendees-invitebox', html::label(null, $this->cal->gettext('sendinvitations') . $checkbox->show(1))) .
html::div(null, $input->show() . " " .
html::tag('input', array('type' => 'button', 'class' => 'button', 'id' => 'edit-attendee-add', 'value' => $this->cal->gettext('addattendee'))) . " " .
html::tag('input', array('type' => 'button', 'class' => 'button', 'id' => 'edit-attendee-schedule', 'value' => $this->cal->gettext('scheduletime').'...'))) .
- html::p('attendees-invitebox', html::label(null, $checkbox->show(1) . $this->cal->gettext('sendinvitations'))) .
- html::p('attendees-commentbox', html::label(null, $this->cal->gettext('comment') . $textarea->show()))
+ html::p('attendees-commentbox', html::label(null, $this->cal->gettext('itipcomment') . $textarea->show()))
);
}
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index 308364f7..8f4bff6e 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -170,7 +170,8 @@ $labels['itipmailbodycancel'] = "\$sender has rejected your participation in the
$labels['itipdeclineevent'] = 'Do you want to decline your invitation to this event?';
$labels['declinedeleteconfirm'] = 'Do you also want to delete this declined event from your calendar?';
-$labels['itipcommenttitle'] = 'This comment will be attached to the invitation/notification message send to participants';
+$labels['itipcomment'] = 'Invitation/notification comment';
+$labels['itipcommenttitle'] = 'This comment will be attached to the invitation/notification message sent to participants';
$labels['notanattendee'] = 'You\'re not listed as an attendee of this event';
$labels['eventcancelled'] = 'The event has been cancelled';
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 43c7a353..72915094 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -845,9 +845,8 @@ td.topalign {
.edit-attendees-table th.options,
.edit-attendees-table td.options {
- width: 3em;
- text-align: right;
- padding-right: 4px;
+ width: 40px;
+ padding: 2px 4px;
}
.edit-attendees-table th.name,
@@ -858,8 +857,12 @@ td.topalign {
text-overflow: ellipsis;
}
+.edit-attendees-table td.name select {
+ width: 100%;
+}
+
.edit-attendees-table a.deletelink {
- display: block;
+ display: inline-block;
width: 17px;
height: 17px;
padding: 0;
@@ -870,16 +873,28 @@ td.topalign {
#edit-attendees-form,
#edit-resources-form {
position: relative;
- margin-top: 1em;
+ margin-top: 3px;
+}
+
+#edit-attendees-form .attendees-invitebox {
+ text-align: right;
+ margin: 0;
+}
+
+#edit-attendees-form .attendees-invitebox label {
+ padding-right: 3px;
}
-#edit-attendees-form #edit-attendee-schedule,
#edit-resources-form #edit-resource-find {
position: absolute;
top: 0;
right: 0;
}
+#edit-attendees-form #edit-attendee-schedule {
+ margin-left: 20px;
+}
+
.edit-attendees-table select.edit-attendee-role {
border: 0;
padding: 2px;
@@ -1124,10 +1139,8 @@ td.topalign {
text-align: center;
}
-#eventedit .attendees-commentbox textarea {
- width: auto;
- margin-left: 10px;
- vertical-align: middle;
+#eventedit .attendees-commentbox label {
+ display: block;
}
a.dropdown-link {