Invitaton handling: show current invitation status in mail view (asynchronously)
This commit is contained in:
parent
08a1a99d27
commit
166bf43f2d
5 changed files with 140 additions and 27 deletions
|
@ -600,6 +600,37 @@ class calendar extends rcube_plugin
|
||||||
|
|
||||||
break;
|
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":
|
case "rsvp":
|
||||||
$ev = $this->driver->get_event($event);
|
$ev = $this->driver->get_event($event);
|
||||||
$ev['attendees'] = $event['attendees'];
|
$ev['attendees'] = $event['attendees'];
|
||||||
|
@ -774,6 +805,7 @@ class calendar extends rcube_plugin
|
||||||
$identity = $rec;
|
$identity = $rec;
|
||||||
$identity['emails'][] = $rec['email'];
|
$identity['emails'][] = $rec['email'];
|
||||||
}
|
}
|
||||||
|
$identity['emails'][] = $this->rc->user->get_username();
|
||||||
$settings['identity'] = array('name' => $identity['name'], 'email' => $identity['email'], 'emails' => ';' . join(';', $identity['emails']));
|
$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') {
|
else if ($this->ical->method == 'REQUEST') {
|
||||||
$title = $event['SEQUENCE'] > 0 ? $this->gettext('itipupdate') : $this->gettext('itipinvitation');
|
$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
|
// add (hidden) buttons and activate them from asyncronous request
|
||||||
if (!$event['SEQUENCE']) {
|
foreach (array('accepted','tentative','declined') as $method) {
|
||||||
foreach (array('accepted','tentative','declined') as $method) {
|
$rsvp_buttons .= html::tag('input', array(
|
||||||
$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(
|
|
||||||
'type' => 'button',
|
'type' => 'button',
|
||||||
'class' => 'button',
|
'class' => 'button',
|
||||||
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "')",
|
'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id.':'.$idx) . "', '$method')",
|
||||||
'value' => $this->gettext('importtocalendar'),
|
'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') {
|
else if ($this->ical->method == 'CANCEL') {
|
||||||
$title = $this->gettext('itipcancellation');
|
$title = $this->gettext('itipcancellation');
|
||||||
|
@ -1627,7 +1662,7 @@ class calendar extends rcube_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// add box below messsage body
|
// 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
|
// limit listing
|
||||||
if ($idx >= 3)
|
if ($idx >= 3)
|
||||||
|
@ -1691,10 +1726,8 @@ class calendar extends rcube_plugin
|
||||||
|
|
||||||
// update my attendee status according to submitted method
|
// update my attendee status according to submitted method
|
||||||
if (!empty($status)) {
|
if (!empty($status)) {
|
||||||
$emails = array($this->rc->user->get_username());
|
|
||||||
foreach ($this->rc->user->list_identities() as $identity)
|
|
||||||
$emails[] = $identity['email'];
|
|
||||||
$organizer = null;
|
$organizer = null;
|
||||||
|
$emails = $this->get_user_emails();
|
||||||
foreach ($event['attendees'] as $i => $attendee) {
|
foreach ($event['attendees'] as $i => $attendee) {
|
||||||
if ($attendee['role'] == 'ORGANIZER') {
|
if ($attendee['role'] == 'ORGANIZER') {
|
||||||
$organizer = $attendee;
|
$organizer = $attendee;
|
||||||
|
@ -1706,7 +1739,7 @@ class calendar extends rcube_plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// save to calendar
|
// save to calendar
|
||||||
if ($calendar && !$calendar['readonly'] && $status != 'declined') {
|
if ($calendar && !$calendar['readonly']) {
|
||||||
$event['id'] = $event['uid'];
|
$event['id'] = $event['uid'];
|
||||||
$event['calendar'] = $calendar['id'];
|
$event['calendar'] = $calendar['id'];
|
||||||
|
|
||||||
|
@ -1751,14 +1784,21 @@ class calendar extends rcube_plugin
|
||||||
}
|
}
|
||||||
// import the (newer) event
|
// import the (newer) event
|
||||||
// TODO: compare SEQUENCE numbers instead of changed dates
|
// 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);
|
$success = $this->driver->edit_event($event);
|
||||||
|
}
|
||||||
|
else if (!empty($status)) {
|
||||||
|
$existing['attendees'] = $event['attendees'];
|
||||||
|
$success = $this->driver->edit_event($existing);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
$error_msg = $this->gettext('newerversionexists');
|
$error_msg = $this->gettext('newerversionexists');
|
||||||
}
|
}
|
||||||
else if (!$existing) {
|
else if (!$existing && $status != 'declined') {
|
||||||
$success = $this->driver->new_event($event);
|
$success = $this->driver->new_event($event);
|
||||||
}
|
}
|
||||||
|
else if ($status == 'declined')
|
||||||
|
$error_msg = null;
|
||||||
}
|
}
|
||||||
else if ($status == 'declined')
|
else if ($status == 'declined')
|
||||||
$error_msg = null;
|
$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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,19 @@ rcube_calendar.add_event_from_mail = function(mime_id, status)
|
||||||
return false;
|
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
|
// extend jQuery
|
||||||
(function($){
|
(function($){
|
||||||
|
@ -187,8 +200,19 @@ rcube_calendar.add_event_from_mail = function(mime_id, status)
|
||||||
window.rcmail && rcmail.addEventListener('init', function(evt) {
|
window.rcmail && rcmail.addEventListener('init', function(evt) {
|
||||||
if (rcmail.task != 'calendar') {
|
if (rcmail.task != 'calendar') {
|
||||||
var cal = new rcube_calendar(rcmail.env.calendar_settings);
|
var cal = new rcube_calendar(rcmail.env.calendar_settings);
|
||||||
|
|
||||||
rcmail.addEventListener('plugin.display_alarms', function(alarms){ cal.display_alarms(alarms); });
|
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){
|
rcmail.addEventListener('plugin.ping_url', function(p){
|
||||||
var action = p.action;
|
var action = p.action;
|
||||||
p.action = p.event = null;
|
p.action = p.event = null;
|
||||||
|
|
|
@ -311,15 +311,25 @@ class kolab_driver extends calendar_driver
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move a single event
|
* Fetch a single event
|
||||||
*
|
*
|
||||||
* @see calendar_driver::get_event()
|
* @see calendar_driver::get_event()
|
||||||
* @return array Hash array with event properties, false if not found
|
* @return array Hash array with event properties, false if not found
|
||||||
*/
|
*/
|
||||||
public function get_event($event)
|
public function get_event($event)
|
||||||
{
|
{
|
||||||
if ($storage = $this->calendars[$event['calendar']])
|
$id = $event['id'] ? $event['id'] : $event['uid'];
|
||||||
return $storage->get_event($event['id']);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,9 @@ $labels['itipmailbodydeclined'] = "\$sender has declined the invitation to the f
|
||||||
$labels['importtocalendar'] = 'Save to my calendar';
|
$labels['importtocalendar'] = 'Save to my calendar';
|
||||||
$labels['updateattendeestatus'] = 'Update the participant\'s status';
|
$labels['updateattendeestatus'] = 'Update the participant\'s status';
|
||||||
$labels['acceptinvitation'] = 'Do you accept this invitation?';
|
$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
|
// event dialog tabs
|
||||||
$labels['tabsummary'] = 'Summary';
|
$labels['tabsummary'] = 'Summary';
|
||||||
|
|
|
@ -1111,6 +1111,7 @@ div.calendar-invitebox td.label {
|
||||||
}
|
}
|
||||||
|
|
||||||
#event-rsvp .rsvp-buttons,
|
#event-rsvp .rsvp-buttons,
|
||||||
|
div.calendar-invitebox .rsvp-status,
|
||||||
div.calendar-invitebox .rsvp-buttons {
|
div.calendar-invitebox .rsvp-buttons {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
@ -1120,3 +1121,25 @@ div.calendar-invitebox input.button {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
margin-right: 0.5em;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue