Improve calendar refreshing after saving an event (#383)

This commit is contained in:
Thomas 2011-08-31 23:40:24 +02:00
parent c4633e0344
commit fb95e89345
2 changed files with 76 additions and 42 deletions

View file

@ -557,24 +557,24 @@ class calendar extends rcube_plugin
$event['id'] = $event['uid']; $event['id'] = $event['uid'];
$this->cleanup_event($event); $this->cleanup_event($event);
} }
$reload = true; $reload = $success && $event['recurrence'] ? 2 : 1;
break; break;
case "edit": case "edit":
$this->prepare_event($event, $action); $this->prepare_event($event, $action);
if ($success = $this->driver->edit_event($event)) if ($success = $this->driver->edit_event($event))
$this->cleanup_event($event); $this->cleanup_event($event);
$reload = true; $reload = $success && $event['recurrence'] ? 2 : 1;
break; break;
case "resize": case "resize":
$success = $this->driver->resize_event($event); $success = $this->driver->resize_event($event);
$reload = true; $reload = ($event['savemode'] == 'all' || $event['savemode'] == 'future') ? 2 : 1;
break; break;
case "move": case "move":
$success = $this->driver->move_event($event); $success = $this->driver->move_event($event);
$reload = true; $reload = $success && ($event['savemode'] == 'all' || $event['savemode'] == 'future') ? 2 : 1;
break; break;
case "remove": case "remove":
@ -591,7 +591,7 @@ class calendar extends rcube_plugin
} }
$success = $this->driver->remove_event($event, $undo_time < 1); $success = $this->driver->remove_event($event, $undo_time < 1);
$reload = true; $reload = (!$success || $event['savemode'] == 'all' || $event['savemode'] == 'future') ? 2 : 1;
if ($undo_time > 0 && $success) { if ($undo_time > 0 && $success) {
$_SESSION['calendar_event_undo'] = array('ts' => time(), 'data' => $event); $_SESSION['calendar_event_undo'] = array('ts' => time(), 'data' => $event);
@ -628,7 +628,6 @@ class calendar extends rcube_plugin
case "undo": case "undo":
// Restore deleted event // Restore deleted event
$event = $_SESSION['calendar_event_undo']['data']; $event = $_SESSION['calendar_event_undo']['data'];
$reload = true;
if ($event) if ($event)
$success = $this->driver->restore_event($event); $success = $this->driver->restore_event($event);
@ -637,6 +636,7 @@ class calendar extends rcube_plugin
$this->rc->session->remove('calendar_event_undo'); $this->rc->session->remove('calendar_event_undo');
$this->rc->output->show_message('calendar.successrestore', 'confirmation'); $this->rc->output->show_message('calendar.successrestore', 'confirmation');
$got_msg = true; $got_msg = true;
$reload = 2;
} }
break; break;
@ -724,9 +724,15 @@ class calendar extends rcube_plugin
// unlock client // unlock client
$this->rc->output->command('plugin.unlock_saving'); $this->rc->output->command('plugin.unlock_saving');
// FIXME: update a single event object on the client instead of reloading the entire source // update event object on the client or trigger a complete refretch if too complicated
if ($reload) if ($reload) {
$this->rc->output->command('plugin.refresh_calendar', array('source' => $event['calendar'], 'refetch' => $success)); $args = array('source' => $event['calendar']);
if ($reload > 1)
$args['refetch'] = true;
else if ($success && $action != 'remove')
$args['update'] = $this->_client_event($this->driver->get_event($event));
$this->rc->output->command('plugin.refresh_calendar', $args);
}
} }
/** /**
@ -873,24 +879,32 @@ class calendar extends rcube_plugin
{ {
$json = array(); $json = array();
foreach ($events as $event) { foreach ($events as $event) {
// compose a human readable strings for alarms_text and recurrence_text $json[] = $this->_client_event($event);
if ($event['alarms'])
$event['alarms_text'] = $this->_alarms_text($event['alarms']);
if ($event['recurrence'])
$event['recurrence_text'] = $this->_recurrence_text($event['recurrence']);
$json[] = array(
'start' => gmdate('c', $this->fromGMT($event['start'])), // client treats date strings as they were in users's timezone
'end' => gmdate('c', $this->fromGMT($event['end'])), // so shift timestamps to users's timezone and render a date string
'description' => strval($event['description']),
'location' => strval($event['location']),
'className' => ($addcss ? 'fc-event-cal-'.asciiwords($event['calendar'], true).' ' : '') . 'fc-event-cat-' . asciiwords($event['categories'], true),
'allDay' => ($event['allday'] == 1),
) + $event;
} }
return json_encode($json); return json_encode($json);
} }
/**
* Convert an event object to be used on the client
*/
private function _client_event($event)
{
// compose a human readable strings for alarms_text and recurrence_text
if ($event['alarms'])
$event['alarms_text'] = $this->_alarms_text($event['alarms']);
if ($event['recurrence'])
$event['recurrence_text'] = $this->_recurrence_text($event['recurrence']);
return array(
'start' => gmdate('c', $this->fromGMT($event['start'])), // client treats date strings as they were in users's timezone
'end' => gmdate('c', $this->fromGMT($event['end'])), // so shift timestamps to users's timezone and render a date string
'description' => strval($event['description']),
'location' => strval($event['location']),
'className' => ($addcss ? 'fc-event-cal-'.asciiwords($event['calendar'], true).' ' : '') . 'fc-event-cat-' . asciiwords($event['categories'], true),
'allDay' => ($event['allday'] == 1),
) + $event;
}
/** /**
* Generate reduced and streamlined output for pending alarms * Generate reduced and streamlined output for pending alarms

View file

@ -1429,10 +1429,12 @@ function rcube_calendar_ui(settings)
rcmail.http_post('event', { action:action, e:data }); rcmail.http_post('event', { action:action, e:data });
// render event temporarily into the calendar // render event temporarily into the calendar
if (data.start && data.end && action != 'remove') { if ((data.start && data.end) || data.id) {
var event = data.id ? $.extend(fc.fullCalendar('clientEvents', data.id)[0], data) : data; var event = data.id ? $.extend(fc.fullCalendar('clientEvents', data.id)[0], data) : data;
event.start = fromunixtime(data.start); if (data.start)
event.end = fromunixtime(data.end); event.start = fromunixtime(data.start);
if (data.end)
event.end = fromunixtime(data.end);
if (data.allday !== undefined) if (data.allday !== undefined)
event.allDay = data.allday; event.allDay = data.allday;
event.editable = false; event.editable = false;
@ -1534,7 +1536,7 @@ function rcube_calendar_ui(settings)
$dialog.dialog({ $dialog.dialog({
modal: true, modal: true,
width: 420, width: 460,
dialogClass: 'warning', dialogClass: 'warning',
title: rcmail.gettext((action == 'remove' ? 'removeeventconfirm' : 'changeeventconfirm'), 'calendar'), title: rcmail.gettext((action == 'remove' ? 'removeeventconfirm' : 'changeeventconfirm'), 'calendar'),
buttons: buttons, buttons: buttons,
@ -2347,24 +2349,42 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
rcmail.register_command('reset-search', function(){ cal.reset_quicksearch(); }, true); rcmail.register_command('reset-search', function(){ cal.reset_quicksearch(); }, true);
// register callback commands // register callback commands
rcmail.addEventListener('plugin.refresh_calendar', function(p){
var source = cal.calendars[p.source];
if (p.refetch && source) {
// activate event source if new event was added to an invisible calendar
if (!source.active) {
source.active = true;
$('#calendar').fullCalendar('addEventSource', source);
$('#' + rcmail.get_folder_li(source.id, 'rcmlical').id + ' input').prop('checked', true);
}
else
$('#calendar').fullCalendar('refetchEvents', source);
}
// remove temp events
$('#calendar').fullCalendar('removeEvents', function(e){ return e.temp; });
});
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.destroy_source', function(p){ cal.calendar_destroy_source(p.id); }); rcmail.addEventListener('plugin.destroy_source', function(p){ cal.calendar_destroy_source(p.id); });
rcmail.addEventListener('plugin.unlock_saving', function(p){ rcmail.set_busy(false, null, cal.saving_lock); }); rcmail.addEventListener('plugin.unlock_saving', function(p){ rcmail.set_busy(false, null, cal.saving_lock); });
rcmail.addEventListener('plugin.refresh_calendar', function(p){
var fc = $('#calendar');
var source = cal.calendars[p.source];
if (source && (p.refetch || (p.update && !source.active))) {
// activate event source if new event was added to an invisible calendar
if (!source.active) {
source.active = true;
fc.fullCalendar('addEventSource', source);
$('#' + rcmail.get_folder_li(source.id, 'rcmlical').id + ' input').prop('checked', true);
}
else
fc.fullCalendar('refetchEvents', source);
}
// add/update single event object
else if (source && p.update) {
var event = p.update;
event.temp = false;
event.editable = source.editable;
var existing = fc.fullCalendar('clientEvents', event.id);
if (existing.length) {
$.extend(existing[0], event);
fc.fullCalendar('updateEvent', existing[0]);
}
else {
event.source = source; // link with source
fc.fullCalendar('renderEvent', event);
}
}
// remove temp events
fc.fullCalendar('removeEvents', function(e){ return e.temp; });
});
// let's go // let's go
var cal = new rcube_calendar_ui(rcmail.env.calendar_settings); var cal = new rcube_calendar_ui(rcmail.env.calendar_settings);