Support free/busy types (e.g. tentative, out-of-office)

This commit is contained in:
Thomas Bruederli 2011-07-23 12:18:29 +02:00
parent 4555108baa
commit be0e774998
6 changed files with 41 additions and 13 deletions

View file

@ -29,6 +29,7 @@ class calendar extends rcube_plugin
const FREEBUSY_UNKNOWN = 0;
const FREEBUSY_FREE = 1;
const FREEBUSY_BUSY = 2;
const FREEBUSY_TENTATIVE = 3;
const FREEBUSY_OOF = 4;
public $task = '?(?!login|logout).*';
@ -1206,6 +1207,7 @@ class calendar extends rcube_plugin
if (!$start) $start = time();
if (!$end) $end = $start + 3600;
$fbtypemap = array(calendar::FREEBUSY_FREE => 'FREE', calendar::FREEBUSY_BUSY => 'BUSY', calendar::FREEBUSY_TENTATIVE => 'TENTATIVE', calendar::FREEBUSY_OOF => 'OUT-OF-OFFICE');
$status = 'UNKNOWN';
// if the backend has free-busy information
@ -1214,9 +1216,9 @@ class calendar extends rcube_plugin
$status = 'FREE';
foreach ($fblist as $slot) {
list($from, $to) = $slot;
list($from, $to, $type) = $slot;
if ($from <= $end && $to > $start) {
$status = 'BUSY';
$status = $type && $fbtypemap[$type] ? $fbtypemap[$type] : 'BUSY';
break;
}
}
@ -1256,9 +1258,9 @@ class calendar extends rcube_plugin
if (is_array($fblist)) {
$status = self::FREEBUSY_FREE;
foreach ($fblist as $slot) {
list($from, $to) = $slot;
list($from, $to, $type) = $slot;
if ($from <= $t_end && $to > $t) {
$status = self::FREEBUSY_BUSY;
$status = isset($type) ? $type : self::FREEBUSY_BUSY;
break;
}
}

View file

@ -46,6 +46,7 @@ function rcube_calendar_ui(settings)
var attendees_list;
var freebusy_ui = {};
var freebusy_data = {};
var freebusy_needsupdate;
// general datepicker settings
var datepicker_settings = {
@ -330,6 +331,7 @@ function rcube_calendar_ui(settings)
var $dialog = $("#eventedit");
var calendar = event.calendar && me.calendars[event.calendar] ? me.calendars[event.calendar] : { editable:action=='new' };
me.selected_event = event;
freebusy_needsupdate = false;
// reset dialog first, enable/disable fields according to editable state
$('#eventtabs').get(0).reset();
@ -799,8 +801,8 @@ function rcube_calendar_ui(settings)
var allday = $('#edit-allday').get(0);
me.selected_event.start = parse_datetime(allday.checked ? '00:00' : $('#edit-starttime').val(), $('#edit-startdate').val());
me.selected_event.end = parse_datetime(allday.checked ? '23:59' : $('#edit-endtime').val(), $('#edit-enddate').val());
if (me.selected_event.attendees)
update_freebusy_status(me.selected_event);
if (event_attendees)
freebusy_needsupdate = true;
$('#edit-startdate').data('duration', Math.round((me.selected_event.end.getTime() - me.selected_event.start.getTime()) / 1000));
}
};
@ -902,10 +904,12 @@ function rcube_calendar_ui(settings)
var update_freebusy_status = function(event)
{
var icons = attendees_list.find('img.availabilityicon');
for (var i=0; i < event.attendees.length; i++) {
if (icons.get(i) && event.attendees[i].email && event.attendees[i].status != 'ACCEPTED')
check_freebusy_status(icons.get(i), event.attendees[i].email, event);
for (var i=0; i < event_attendees.length; i++) {
if (icons.get(i) && event_attendees[i].email && event_attendees[i].status != 'ACCEPTED')
check_freebusy_status(icons.get(i), event_attendees[i].email, event);
}
freebusy_needsupdate = false;
};
// load free-busy status from server and update icon accordingly
@ -1563,8 +1567,11 @@ function rcube_calendar_ui(settings)
// init event dialog
$('#eventtabs').tabs({
show: function(event, ui) {
if (ui.panel.id == 'event-tab-3')
if (ui.panel.id == 'event-tab-3') {
$('#edit-attendee-name').select();
if (freebusy_needsupdate && me.selected_event)
update_freebusy_status(me.selected_event);
}
}
});
$('#edit-enddate, input.edit-alarm-date').datepicker(datepicker_settings);

View file

@ -693,9 +693,19 @@ class kolab_driver extends calendar_driver
if (empty($email)/* || $end < time()*/)
return false;
// map vcalendar fbtypes to internal values
$fbtypemap = array(
'FREE' => calendar::FREEBUSY_FREE,
'BUSY-TENTATIVE' => calendar::FREEBUSY_TENTATIVE,
'X-OUT-OF-OFFICE' => calendar::FREEBUSY_OOF,
'OOF' => calendar::FREEBUSY_OOF);
// ask kolab server first
$fbdata = @file_get_contents(rcube_kolab::get_freebusy_url($email));
if (!$fbdata)
$fbdata = file_get_contents('http://localhost/roundcube/kolab/sample.ifb');
// get free-busy url from contacts
if (!$fbdata) {
$fburl = null;
@ -722,10 +732,12 @@ class kolab_driver extends calendar_driver
$fbcal->parsevCalendar($fbdata);
if ($fb = $fbcal->findComponent('vfreebusy')) {
$result = array();
$params = $fb->getExtraParams();
foreach ($fb->getBusyPeriods() as $from => $to) {
if ($to == null) // no information, assume free
break;
$result[] = array($from, $to);
$type = $params[$from]['FBTYPE'];
$result[] = array($from, $to, isset($fbtypemap[$type]) ? $fbtypemap[$type] : calendar::FREEBUSY_BUSY);
}
return $result;

View file

@ -95,6 +95,7 @@ $labels['roleresource'] = 'Resource';
$labels['availfree'] = 'Free';
$labels['availbusy'] = 'Busy';
$labels['availunknown'] = 'Unknown';
$labels['availtentative'] = 'Tentative';
$labels['availoutofoffice'] = 'Out of Office';
$labels['scheduletime'] = 'Available times';
$labels['sendnotifications'] = 'Send notifications';

View file

@ -566,7 +566,7 @@ td.topalign {
}
.availability img.availabilityicon.loading {
background: url('images/loading-small.gif') top left no-repeat;
background: url('images/loading-small.gif') middle middle no-repeat;
}
#schedule-freebusy-times td.unknown,
@ -584,6 +584,11 @@ td.topalign {
background: #c00;
}
#schedule-freebusy-times td.tentative,
.availability img.availabilityicon.tentative {
background: #66d;
}
#schedule-freebusy-times td.out-of-office,
.availability img.availabilityicon.out-of-office {
background: #f0b400;

View file

@ -1,6 +1,7 @@
<div id="edit-attendees-legend" class="availability">
<span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
<span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
<span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
<span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
<span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
</div>