diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css index 4a035cb0..c8f36b14 100644 --- a/plugins/calendar/skins/larry/calendar.css +++ b/plugins/calendar/skins/larry/calendar.css @@ -2222,6 +2222,11 @@ div.calendar-invitebox td em { font-weight: bold; } +div.calendar-invitebox td.date.modified { + font-weight: bold; + color: red; +} + #event-rsvp .rsvp-buttons, div.calendar-invitebox .itip-buttons div { margin-top: 0.5em; diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php index c6eef240..c7986175 100644 --- a/plugins/libcalendaring/lib/libcalendaring_itip.php +++ b/plugins/libcalendaring/lib/libcalendaring_itip.php @@ -359,8 +359,8 @@ class libcalendaring_itip { $action = $event['rsvp'] ? 'rsvp' : ''; $status = $event['fallback']; - $latest = false; - $html = ''; + $latest = $resheduled = false; + $html = ''; if (is_numeric($event['changed'])) $event['changed'] = new DateTime('@'.$event['changed']); @@ -384,6 +384,13 @@ class libcalendaring_itip break; } } + + // Detect re-sheduling + if (!$latest) { + // FIXME: This is probably to simplistic, or maybe we should just check + // attendee's RSVP flag in the new event? + $resheduled = $existing['start'] != $event['start'] || $existing['end'] > $event['end']; + } } else { $rsvp = $event['rsvp'] && $this->rc->config->get('calendar_allow_itip_uninvited', true); @@ -406,6 +413,9 @@ class libcalendaring_itip else if (!$existing && !$rsvp) { $action = 'import'; } + else if ($resheduled) { + $action = 'rsvp'; + } else if ($status_lc != 'needs-action') { $action = !$latest ? 'update' : ''; } @@ -453,14 +463,15 @@ class libcalendaring_itip } return array( - 'uid' => $event['uid'], - 'id' => asciiwords($event['uid'], true), - 'existing' => $existing ? true : false, - 'saved' => $existing ? true : false, - 'latest' => $latest, - 'status' => $status, - 'action' => $action, - 'html' => $html, + 'uid' => $event['uid'], + 'id' => asciiwords($event['uid'], true), + 'existing' => $existing ? true : false, + 'saved' => $existing ? true : false, + 'latest' => $latest, + 'status' => $status, + 'action' => $action, + 'resheduled' => $resheduled, + 'html' => $html, ); } diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js index 985271e1..c15fa048 100644 --- a/plugins/libcalendaring/libcalendaring.js +++ b/plugins/libcalendaring/libcalendaring.js @@ -1287,10 +1287,14 @@ rcube_libcalendaring.update_itip_object_status = function(p) $('#rsvp-'+p.id+' input.button').prop('disabled', false) .filter('.'+String(p.status||'unknown').toLowerCase()).prop('disabled', p.latest); } - + // show rsvp/import buttons (with calendar selector) $('#'+p.action+'-'+p.id).show().find('input.button').last().after(p.select); + // highlight date if date change detected + if (p.resheduled) + $('.calendar-eventdetails td.date').addClass('modified'); + // show itip box appendix after replacing the given placeholders if (p.append && p.append.selector) { var elem = $(p.append.selector);