Add button to iTip RSVP UI in mail view to open the calendar preview with an option to accept/decline the invitation from there (#3161)

This commit is contained in:
Thomas Bruederli 2014-09-10 10:30:40 +02:00
parent 7161b90e46
commit 09cf967ed5
9 changed files with 128 additions and 9 deletions

View file

@ -309,10 +309,13 @@ class calendar extends rcube_plugin
$view = get_input_value('view', RCUBE_INPUT_GPC);
if (in_array($view, array('agendaWeek', 'agendaDay', 'month', 'table')))
$this->rc->output->set_env('view', $view);
if ($date = get_input_value('date', RCUBE_INPUT_GPC))
$this->rc->output->set_env('date', $date);
if ($msgref = get_input_value('itip', RCUBE_INPUT_GPC))
$this->rc->output->set_env('itip_events', $this->itip_events($msgref));
$this->rc->output->send("calendar.calendar");
}
@ -1122,6 +1125,43 @@ class calendar extends rcube_plugin
exit;
}
/**
* Load event data from an iTip message attachment
*/
public function itip_events($msgref)
{
$path = explode('/', $msgref);
$msg = array_pop($path);
$mbox = join('/', $path);
list($uid, $mime_id) = explode('#', $msg);
$events = array();
if ($event = $this->lib->mail_get_itip_object($mbox, $uid, $mime_id, 'event')) {
$partstat = 'NEEDS-ACTION';
/*
$user_emails = $this->lib->get_user_emails();
foreach ($event['attendees'] as $attendee) {
if (in_array($attendee['email'], $user_emails)) {
$partstat = $attendee['status'];
break;
}
}
*/
$event['id'] = $event['uid'];
$event['temporary'] = true;
$event['readonly'] = true;
$event['calendar'] = '--invitation--itip';
$event['className'] = 'fc-invitation-' . strtolower($partstat);
$event['_mbox'] = $mbox;
$event['_uid'] = $uid;
$event['_part'] = $mime_id;
$events[] = $this->_client_event($event, true);
}
return $events;
}
/**
* Handler for keep-alive requests
* This will check for updated data in active calendars and sync them to the client
@ -2357,7 +2397,8 @@ class calendar extends rcube_plugin
$ical_objects->method,
$ical_objects->mime_id . ':' . $idx,
'calendar',
rcube_utils::anytodatetime($ical_objects->message_date)
rcube_utils::anytodatetime($ical_objects->message_date),
$this->rc->url(array('task' => 'calendar')) . '&view=agendaDay&date=' . $event['start']->format('U')
)
);
}
@ -2566,6 +2607,7 @@ class calendar extends rcube_plugin
}
if ($success || $dontsave) {
$metadata['calendar'] = $event['calendar'];
$metadata['nosave'] = $dontsave;
$metadata['rsvp'] = intval($metadata['rsvp']);
$metadata['after_action'] = $this->rc->config->get('calendar_itip_after_action', $this->defaults['calendar_itip_after_action']);

View file

@ -599,7 +599,7 @@ function rcube_calendar_ui(settings)
me.dialog_resize($dialog.get(0), $dialog.height(), 420);
// add link for "more options" drop-down
if (!temp) {
if (!temp && !event.temporary) {
$('<a>')
.attr('href', '#')
.html(rcmail.gettext('eventoptions','calendar'))
@ -2339,7 +2339,19 @@ function rcube_calendar_ui(settings)
var submit_data = $.extend({}, me.selected_event, { source:null, comment:$('#reply-comment-event-rsvp').val() }),
noreply = $('#noreply-event-rsvp:checked').length ? 1 : 0;
if (settings.invitation_calendars) {
// import event from mail (temporary iTip event)
if (submit_data._mbox && submit_data._uid) {
me.saving_lock = rcmail.set_busy(true, 'calendar.savingdata');
rcmail.http_post('mailimportitip', {
_mbox: submit_data._mbox,
_uid: submit_data._uid,
_part: submit_data._part,
_status: response,
_noreply: noreply,
_comment: submit_data.comment
});
}
else if (settings.invitation_calendars) {
update_event('rsvp', submit_data, { status:response, noreply:noreply });
}
else {
@ -3089,6 +3101,25 @@ function rcube_calendar_ui(settings)
return query;
};
// callback after an iTip message event was imported
this.itip_message_processed = function(data)
{
// remove temporary iTip source
fc.fullCalendar('removeEventSource', this.calendars['--invitation--itip']);
$('#eventshow:ui-dialog').dialog('close');
this.selected_event = null;
// refresh destination calendar source
this.refresh({ source:data.calendar, refetch:true });
this.unlock_saving();
// process 'after_action' in mail task
if (window.opener && window.opener.rcube_libcalendaring)
window.opener.rcube_libcalendaring.itip_message_processed(data);
};
// reload the calendar view by keeping the current date/view selection
this.reload_view = function()
{
@ -3462,7 +3493,20 @@ function rcube_calendar_ui(settings)
var viewdate = new Date();
if (rcmail.env.date)
viewdate.setTime(fromunixtime(rcmail.env.date));
// add source with iTip event data for rendering
if (rcmail.env.itip_events && rcmail.env.itip_events.length) {
me.calendars['--invitation--itip'] = {
events: rcmail.env.itip_events,
className: 'fc-event-cal---invitation--itip',
color: '#fff',
textColor: '#333',
editable: false,
attendees: true
};
event_sources.push(me.calendars['--invitation--itip']);
}
// initalize the fullCalendar plugin
var fc = $('#calendar').fullCalendar($.extend({}, fullcalendar_defaults, {
header: {
@ -3940,6 +3984,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
rcmail.addEventListener('plugin.render_event_changelog', function(data){ cal.render_event_changelog(data); });
rcmail.addEventListener('plugin.event_show_diff', function(data){ cal.event_show_diff(data); });
rcmail.addEventListener('plugin.event_show_revision', function(data){ cal.event_show_dialog(data, null, true); });
rcmail.addEventListener('plugin.itip_message_processed', function(data){ cal.itip_message_processed(data); });
rcmail.addEventListener('requestrefresh', function(q){ return cal.before_refresh(q); });
// let's go

View file

@ -201,6 +201,7 @@ $labels['eventcancelled'] = 'The event has been cancelled';
$labels['saveincalendar'] = 'save in';
$labels['updatemycopy'] = 'Update in my calendar';
$labels['savetocalendar'] = 'Save to calendar';
$labels['openpreview'] = 'Check Calendar';
// resources
$labels['resource'] = 'Resource';

View file

@ -6,7 +6,7 @@
<script type="text/javascript" src="/functions.js"></script>
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="./plugins/calendar/skins/classic/iehacks.css" /><![endif]-->
</head>
<body class="calendarmain">
<roundcube:if condition="env:extwin" /><body class="calendarmain extwin"><roundcube:else /><body class="calendarmain"><roundcube:endif />
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />

View file

@ -1,7 +1,7 @@
/**
* Roundcube Calendar plugin styles for skin "Larry"
*
* Copyright (c) 2012, Kolab Systems AG <contact@kolabsys.com>
* Copyright (c) 2012-2014, Kolab Systems AG <contact@kolabsys.com>
* Screendesign by FLINT / Büro für Gestaltung, bueroflint.com
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
@ -2016,9 +2016,15 @@ div.calendar-invitebox input.button {
margin-right: 0.5em;
}
div.calendar-invitebox input.button.preview {
margin-left: 1em;
margin-right: 0;
}
div.calendar-invitebox .folder-select {
font-weight: 10px;
margin-left: 1em;
white-space: nowrap;
}
div.calendar-invitebox .rsvp-status {

View file

@ -5,7 +5,7 @@
<roundcube:include file="/includes/links.html" />
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/this/iehacks.css" /><![endif]-->
</head>
<body class="calendarmain">
<roundcube:if condition="env:extwin" /><body class="calendarmain extwin"><roundcube:else /><body class="calendarmain"><roundcube:endif />
<roundcube:include file="/includes/header.html" />

View file

@ -361,6 +361,7 @@ 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,
@ -372,7 +373,7 @@ class libcalendaring_itip
/**
* Build inline UI elements for iTip messages
*/
public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null)
public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null, $preview_url = null)
{
$buttons = array();
$dom_id = asciiwords($event['uid'], true);
@ -450,6 +451,17 @@ class libcalendaring_itip
));
}
// add button to open calendar/preview
if (!empty($preview_url)) {
$msgref = $this->lib->ical_message->folder . '/' . $this->lib->ical_message->uid . '#' . $mime_id;
$rsvp_buttons .= html::tag('input', array(
'type' => 'button',
'class' => "button preview",
'onclick' => "rcube_libcalendaring.open_itip_preview('" . JQ($preview_url) . "', '" . JQ($msgref) . "')",
'value' => $this->gettext('openpreview'),
));
}
// 2. update the local copy with minor changes
$update_button = html::tag('input', array(
'type' => 'button',

View file

@ -892,6 +892,7 @@ rcube_libcalendaring.fetch_itip_object_status = function(p)
rcube_libcalendaring.update_itip_object_status = function(p)
{
rcmail.env.rsvp_saved = p.saved;
rcmail.env.itip_existing = p.existing;
// hide all elements first
$('#itip-buttons-'+p.id+' > div').hide();
@ -953,6 +954,17 @@ rcube_libcalendaring.itip_after_action = function(action)
}
};
/**
* Open the calendar preview for the current iTip event
*/
rcube_libcalendaring.open_itip_preview = function(url, msgref)
{
if (!rcmail.env.itip_existing)
url += '&itip=' + escape(msgref);
var win = rcmail.open_window(url);
};
// extend jQuery
(function($){

View file

@ -134,6 +134,7 @@ $labels['outdatedinvitation'] = 'This invitation has been replaced by a newer ve
$labels['importtocalendar'] = 'Save to my calendar';
$labels['removefromcalendar'] = 'Remove from my calendar';
$labels['updatemycopy'] = 'Update my copy';
$labels['openpreview'] = 'Open Preview';
$labels['deleteobjectconfirm'] = 'Do you really want to delete this object?';
$labels['declinedeleteconfirm'] = 'Do you also want to delete this declined object from your account?';