Invitaton handling: show current invitation status in mail view (asynchronously)

This commit is contained in:
Thomas 2011-08-24 17:45:51 +02:00
parent 08a1a99d27
commit 166bf43f2d
5 changed files with 140 additions and 27 deletions

View file

@ -600,6 +600,37 @@ class calendar extends rcube_plugin
break;
case "rsvp-status":
$status = 'unknown';
$action = 'rsvp';
$html = html::div('rsvp-status', $this->gettext('acceptinvitation'));
$this->load_driver();
if ($existing = $this->driver->get_event($event)) {
$emails = $this->get_user_emails();
foreach ($existing['attendees'] as $i => $attendee) {
if ($attendee['email'] && in_array($attendee['email'], $emails)) {
$status = $attendee['status'];
break;
}
}
if (in_array($status, array('ACCEPTED','TENTATIVE','DECLINED'))) {
$html = html::div('rsvp-status ' . strtolower($status), $this->gettext('youhave'.strtolower($status)));
if ($event['changed'] < $existing['changed']) {
$action = '';
}
}
}
$this->rc->output->command('plugin.update_event_rsvp_status', array(
'uid' => $event['uid'],
'id' => asciiwords($event['uid'], true),
'status' => $status,
'action' => $action,
'html' => $html,
));
return;
case "rsvp":
$ev = $this->driver->get_event($event);
$ev['attendees'] = $event['attendees'];
@ -774,6 +805,7 @@ class calendar extends rcube_plugin
$identity = $rec;
$identity['emails'][] = $rec['email'];
}
$identity['emails'][] = $this->rc->user->get_username();
$settings['identity'] = array('name' => $identity['name'], 'email' => $identity['email'], 'emails' => ';' . join(';', $identity['emails']));
}
@ -1577,25 +1609,28 @@ class calendar extends rcube_plugin
else if ($this->ical->method == 'REQUEST') {
$title = $event['SEQUENCE'] > 0 ? $this->gettext('itipupdate') : $this->gettext('itipinvitation');
// TODO: check for a copy in my calendar in order to show the right options
if (!$event['SEQUENCE']) {
foreach (array('accepted','tentative','declined') as $method) {
$buttons .= html::tag('input', array(
'type' => 'button',
'class' => 'button',
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "', '$method')",
'value' => $this->gettext('itip' . $method),
));
}
}
else {
$buttons = html::tag('input', array(
// add (hidden) buttons and activate them from asyncronous request
foreach (array('accepted','tentative','declined') as $method) {
$rsvp_buttons .= html::tag('input', array(
'type' => 'button',
'class' => 'button',
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "')",
'value' => $this->gettext('importtocalendar'),
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "', '$method')",
'value' => $this->gettext('itip' . $method),
));
}
$import_button = html::tag('input', array(
'type' => 'button',
'class' => 'button',
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "')",
'value' => $this->gettext('importtocalendar'),
));
$dom_id = asciiwords($event['uid'], true);
$buttons = html::div(array('id' => 'rsvp-'.$dom_id, 'style' => 'display:none'), $rsvp_buttons);
$buttons .= html::div(array('id' => 'import-'.$dom_id, 'style' => 'display:none'), $import_button);
$buttons_pre = html::div(array('id' => 'loading-'.$dom_id, 'class' => 'rsvp-status loading'), $this->gettext('loading'));
$this->rc->output->add_script('rcube_calendar.fetch_event_rsvp_status(' . json_serialize(array('uid' => $event['uid'], 'changed' => $event['changed'])) . ')', 'docready');
}
else if ($this->ical->method == 'CANCEL') {
$title = $this->gettext('itipcancellation');
@ -1627,7 +1662,7 @@ class calendar extends rcube_plugin
}
// add box below messsage body
$html .= html::div('calendar-invitebox', $table->show() . html::div('rsvp-buttons', $buttons));
$html .= html::div('calendar-invitebox', $table->show() . $buttons_pre . html::div('rsvp-buttons', $buttons));
// limit listing
if ($idx >= 3)
@ -1643,8 +1678,8 @@ class calendar extends rcube_plugin
return $p;
}
/**
* Handler for POST request to import an event attached to a mail message
*/
@ -1691,10 +1726,8 @@ class calendar extends rcube_plugin
// update my attendee status according to submitted method
if (!empty($status)) {
$emails = array($this->rc->user->get_username());
foreach ($this->rc->user->list_identities() as $identity)
$emails[] = $identity['email'];
$organizer = null;
$emails = $this->get_user_emails();
foreach ($event['attendees'] as $i => $attendee) {
if ($attendee['role'] == 'ORGANIZER') {
$organizer = $attendee;
@ -1706,7 +1739,7 @@ class calendar extends rcube_plugin
}
// save to calendar
if ($calendar && !$calendar['readonly'] && $status != 'declined') {
if ($calendar && !$calendar['readonly']) {
$event['id'] = $event['uid'];
$event['calendar'] = $calendar['id'];
@ -1751,14 +1784,21 @@ class calendar extends rcube_plugin
}
// import the (newer) event
// TODO: compare SEQUENCE numbers instead of changed dates
else if ($event['changed'] >= $existing['changed'])
else if ($event['changed'] >= $existing['changed']) {
$success = $this->driver->edit_event($event);
}
else if (!empty($status)) {
$existing['attendees'] = $event['attendees'];
$success = $this->driver->edit_event($existing);
}
else
$error_msg = $this->gettext('newerversionexists');
}
else if (!$existing) {
else if (!$existing && $status != 'declined') {
$success = $this->driver->new_event($event);
}
else if ($status == 'declined')
$error_msg = null;
}
else if ($status == 'declined')
$error_msg = null;
@ -1896,5 +1936,18 @@ class calendar extends rcube_plugin
);
}
/**
* Get a list of email addresses of the current user (from login and identities)
*/
private function get_user_emails()
{
$emails = array($this->rc->user->get_username());
foreach ($this->rc->user->list_identities() as $identity)
$emails[] = $identity['email'];
return array_unique($emails);
}
}

View file

@ -171,6 +171,19 @@ rcube_calendar.add_event_from_mail = function(mime_id, status)
return false;
};
rcube_calendar.fetch_event_rsvp_status = function(event)
{
/*
var id = event.uid.replace(rcmail.identifier_expr, '');
$('#import-'+id+', #rsvp-'+id+', div.rsvp-status').hide();
$('#loading-'+id).show();
*/
rcmail.http_post('calendar/event', {
e:event,
action:'rsvp-status'
});
};
// extend jQuery
(function($){
@ -187,8 +200,19 @@ rcube_calendar.add_event_from_mail = function(mime_id, status)
window.rcmail && rcmail.addEventListener('init', function(evt) {
if (rcmail.task != 'calendar') {
var cal = new rcube_calendar(rcmail.env.calendar_settings);
rcmail.addEventListener('plugin.display_alarms', function(alarms){ cal.display_alarms(alarms); });
rcmail.addEventListener('plugin.update_event_rsvp_status', function(p){
if (p.html)
$('#loading-'+p.id).hide().after(p.html);
else
$('#loading-'+p.id).hide();
$('#'+p.action+'-'+p.id).show();
});
}
rcmail.addEventListener('plugin.ping_url', function(p){
var action = p.action;
p.action = p.event = null;

View file

@ -311,15 +311,25 @@ class kolab_driver extends calendar_driver
/**
* Move a single event
* Fetch a single event
*
* @see calendar_driver::get_event()
* @return array Hash array with event properties, false if not found
*/
public function get_event($event)
{
if ($storage = $this->calendars[$event['calendar']])
return $storage->get_event($event['id']);
$id = $event['id'] ? $event['id'] : $event['uid'];
if ($event['calendar'] && ($storage = $this->calendars[$event['calendar']])) {
return $storage->get_event($id);
}
// iterate over all calendar folders and search for the event ID
else if (!$event['calendar']) {
foreach ($this->calendars as $storage) {
if ($result = $storage->get_event($id)) {
return $result;
}
}
}
return false;
}

View file

@ -138,6 +138,9 @@ $labels['itipmailbodydeclined'] = "\$sender has declined the invitation to the f
$labels['importtocalendar'] = 'Save to my calendar';
$labels['updateattendeestatus'] = 'Update the participant\'s status';
$labels['acceptinvitation'] = 'Do you accept this invitation?';
$labels['youhaveaccepted'] = 'You have accepted this invitation';
$labels['youhavetentative'] = 'You have tentatively accepted this invitation';
$labels['youhavedeclined'] = 'You have declined this invitation';
// event dialog tabs
$labels['tabsummary'] = 'Summary';

View file

@ -1111,6 +1111,7 @@ div.calendar-invitebox td.label {
}
#event-rsvp .rsvp-buttons,
div.calendar-invitebox .rsvp-status,
div.calendar-invitebox .rsvp-buttons {
margin-top: 0.5em;
}
@ -1120,3 +1121,25 @@ div.calendar-invitebox input.button {
font-size: 11px;
margin-right: 0.5em;
}
div.calendar-invitebox .rsvp-status.loading {
color: #666;
padding: 1px 0 2px 24px;
background: url('images/loading-small.gif') top left no-repeat;
}
div.calendar-invitebox .rsvp-status.declined,
div.calendar-invitebox .rsvp-status.tentative,
div.calendar-invitebox .rsvp-status.accepted {
padding: 0 0 1px 22px;
background: url('images/attendee-status.gif') 2px -20px no-repeat;
}
div.calendar-invitebox .rsvp-status.declined {
background-position: 2px -40px;
}
div.calendar-invitebox .rsvp-status.tentative {
background-position: 2px -60px;
}