Improve free/busy UI according to inputs from Georg
This commit is contained in:
parent
8b8142db53
commit
322f649d77
8 changed files with 99 additions and 7 deletions
|
@ -1395,8 +1395,8 @@ class calendar extends rcube_plugin
|
|||
}
|
||||
}
|
||||
|
||||
// let this information be cached for 15min
|
||||
send_future_expire_header(900);
|
||||
// let this information be cached for 5min
|
||||
send_future_expire_header(300);
|
||||
|
||||
echo $status;
|
||||
exit;
|
||||
|
@ -1441,6 +1441,9 @@ class calendar extends rcube_plugin
|
|||
$t = $t_end;
|
||||
}
|
||||
|
||||
// let this information be cached for 5min
|
||||
send_future_expire_header(300);
|
||||
|
||||
echo json_encode(array('email' => $email, 'start' => intval($start), 'end' => intval($t_end), 'interval' => $interval, 'slots' => $slots));
|
||||
exit;
|
||||
}
|
||||
|
|
|
@ -673,7 +673,7 @@ function rcube_calendar_ui(settings)
|
|||
fb_start.setHours(0); fb_start.setMinutes(0); fb_start.setSeconds(0); fb_start.setMilliseconds(0);
|
||||
fb_end.setTime(fb_start.getTime() + DAY_MS);
|
||||
|
||||
freebusy_data = {};
|
||||
freebusy_data = { required:{}, all:{} };
|
||||
freebusy_ui.loading = 1; // prevent render_freebusy_grid() to load data yet
|
||||
freebusy_ui.numdays = allday.checked ? 7 : Math.ceil(duration * 2 / 86400);
|
||||
freebusy_ui.interval = allday.checked ? 360 : 60;
|
||||
|
@ -690,6 +690,10 @@ function rcube_calendar_ui(settings)
|
|||
list_html += '<div class="attendee ' + String(data.role).toLowerCase() + '" id="rcmli' + domid + '">' + dispname + '</div>';
|
||||
}
|
||||
|
||||
// add total row
|
||||
list_html += '<div class="attendee spacer"> </div>';
|
||||
list_html += '<div class="attendee total">' + rcmail.gettext('reqallattendees','calendar') + '</div>';
|
||||
|
||||
$('#schedule-attendees-list').html(list_html);
|
||||
|
||||
// enable/disable buttons
|
||||
|
@ -781,6 +785,10 @@ function rcube_calendar_ui(settings)
|
|||
times_html += '<tr id="fbrow' + domid + '">' + slots_row + '</tr>';
|
||||
}
|
||||
|
||||
// add line for all/required attendees
|
||||
times_html += '<tr class="spacer"><td colspan="' + (dayslots * freebusy_ui.numdays) + '"> </td>';
|
||||
times_html += '<tr id="fbrowall">' + slots_row + '</tr>';
|
||||
|
||||
var table = $('#schedule-freebusy-times');
|
||||
table.children('thead').html(dates_row + times_row);
|
||||
table.children('tbody').html(times_html);
|
||||
|
@ -905,9 +913,10 @@ function rcube_calendar_ui(settings)
|
|||
{
|
||||
var start = new Date(from.getTime() - DAY_MS * 2); // start 1 days before event
|
||||
var end = new Date(start.getTime() + DAY_MS * 14); // load 14 days
|
||||
freebusy_ui.numrequired = 0;
|
||||
|
||||
// load free-busy information for every attendee
|
||||
var domid, email
|
||||
var domid, email;
|
||||
for (var i=0; i < event_attendees.length; i++) {
|
||||
if ((email = event_attendees[i].email)) {
|
||||
domid = String(email).replace(rcmail.identifier_expr, '');
|
||||
|
@ -918,16 +927,37 @@ function rcube_calendar_ui(settings)
|
|||
type: 'GET',
|
||||
dataType: 'json',
|
||||
url: rcmail.url('freebusy-times'),
|
||||
data: { email:email, start:date2unixtime(start), end:date2unixtime(end), interval:interval, _remote: 1 },
|
||||
success: function(data){
|
||||
data: { email:email, start:date2unixtime(start), end:date2unixtime(end), interval:interval, _remote:1 },
|
||||
success: function(data) {
|
||||
freebusy_ui.loading--;
|
||||
|
||||
// find attendee
|
||||
var attendee = null;
|
||||
for (var i=0; i < event_attendees.length; i++) {
|
||||
if (event_attendees[i].email == data.email) {
|
||||
attendee = event_attendees[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// copy data to member var
|
||||
var req = attendee.role != 'OPT-PARTICIPANT';
|
||||
var ts = data.start - 0;
|
||||
freebusy_data.start = ts;
|
||||
freebusy_data[data.email] = {};
|
||||
for (var i=0; i < data.slots.length; i++) {
|
||||
freebusy_data[data.email][ts] = data.slots[i];
|
||||
|
||||
// set totals
|
||||
if (!freebusy_data.required[ts])
|
||||
freebusy_data.required[ts] = [0,0,0,0];
|
||||
if (req)
|
||||
freebusy_data.required[ts][data.slots[i]]++;
|
||||
|
||||
if (!freebusy_data.all[ts])
|
||||
freebusy_data.all[ts] = [0,0,0,0];
|
||||
freebusy_data.all[ts][data.slots[i]]++;
|
||||
|
||||
ts += data.interval * 60;
|
||||
}
|
||||
freebusy_data.end = ts;
|
||||
|
@ -941,6 +971,10 @@ function rcube_calendar_ui(settings)
|
|||
update_freebusy_display(data.email);
|
||||
}
|
||||
});
|
||||
|
||||
// count required attendees
|
||||
if (event_attendees[i].role != 'OPT-PARTICIPANT')
|
||||
freebusy_ui.numrequired++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -951,12 +985,28 @@ function rcube_calendar_ui(settings)
|
|||
var status_classes = ['unknown','free','busy','tentative','out-of-office'];
|
||||
var domid = String(email).replace(rcmail.identifier_expr, '');
|
||||
var row = $('#fbrow' + domid);
|
||||
var rowall = $('#fbrowall').children();
|
||||
var ts = date2unixtime(freebusy_ui.start);
|
||||
var fbdata = freebusy_data[email];
|
||||
|
||||
if (fbdata && fbdata[ts] && row.length) {
|
||||
row.children().each(function(i, cell){
|
||||
cell.className = cell.className.replace('unknown', fbdata[ts] ? status_classes[fbdata[ts]] : 'unknown');
|
||||
|
||||
// also update total row if all data was loaded
|
||||
if (freebusy_ui.loading == 0 && freebusy_data.all[ts] && (cell = rowall.get(i))) {
|
||||
var all_status = freebusy_data.all[ts][2] ? 'busy' : 'unknown';
|
||||
req_status = freebusy_data.required[ts][2] ? 'busy' : 'free';
|
||||
for (var j=0; j < status_classes.length; j++) {
|
||||
if (freebusy_ui.numrequired && freebusy_data.required[ts][j] >= freebusy_ui.numrequired)
|
||||
req_status = status_classes[j];
|
||||
if (freebusy_data.all[ts][j] == event_attendees.length)
|
||||
all_status = status_classes[j];
|
||||
}
|
||||
|
||||
cell.className = cell.className.replace('unknown', req_status + ' all-' + all_status);
|
||||
}
|
||||
|
||||
ts += freebusy_ui.interval * 60;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -806,6 +806,10 @@ class kolab_driver extends calendar_driver
|
|||
if (($fbstart = $fb->getStart()) && $start < $fbstart) {
|
||||
array_unshift($result, array($start, $fbstart, calendar::FREEBUSY_UNKNOWN));
|
||||
}
|
||||
// pad period till $end with status 'unknown'
|
||||
if (($fbend = $fb->getEnd()) && $fbend < $end) {
|
||||
$result[] = array($fbend, $end, calendar::FREEBUSY_UNKNOWN);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ $labels['scheduletime'] = 'Find availability';
|
|||
$labels['sendinvitations'] = 'Send invitations';
|
||||
$labels['sendnotifications'] = 'Notify attendees about modifications';
|
||||
$labels['onlyworkinghours'] = 'Find availability within my working hours';
|
||||
$labels['reqallattendees'] = 'Required/all participants';
|
||||
$labels['prevslot'] = 'Previous Slot';
|
||||
$labels['nextslot'] = 'Next Slot';
|
||||
$labels['noslotfound'] = 'Unable to find a free time slot';
|
||||
|
|
|
@ -602,6 +602,22 @@ td.topalign {
|
|||
background: #f0b400;
|
||||
}
|
||||
|
||||
#schedule-freebusy-times td.all-busy,
|
||||
#schedule-freebusy-times td.all-tentative,
|
||||
#schedule-freebusy-times td.all-out-of-office {
|
||||
background-image: url('images/freebusy-colors.png');
|
||||
background-position: top right;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#schedule-freebusy-times td.all-tentative {
|
||||
background-position: right -40px;
|
||||
}
|
||||
|
||||
#schedule-freebusy-times td.all-out-of-office {
|
||||
background-position: right -80px;
|
||||
}
|
||||
|
||||
#edit-attendees-legend {
|
||||
margin-top: 3em;
|
||||
margin-bottom: 0.5em;
|
||||
|
@ -704,6 +720,18 @@ td.topalign {
|
|||
background: url('images/loading-small.gif') 1px 50% no-repeat;
|
||||
}
|
||||
|
||||
.attendees-list .total {
|
||||
background: none;
|
||||
padding-left: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.attendees-list .spacer,
|
||||
#schedule-freebusy-times tr.spacer td {
|
||||
background: 0;
|
||||
font-size: 50%;
|
||||
}
|
||||
|
||||
#schedule-freebusy-times {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
|
|
@ -51,4 +51,10 @@ html #calendartoolbar a.buttonPas {
|
|||
#eventfreebusy .schedule-buttons,
|
||||
#edit-attendees-form #edit-attendee-schedule {
|
||||
right: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
#schedule-freebusy-times td.all-busy,
|
||||
#schedule-freebusy-times td.all-tentative,
|
||||
#schedule-freebusy-times td.all-out-of-office {
|
||||
background-image: url('images/freebusy-colors.gif');
|
||||
}
|
||||
|
|
BIN
plugins/calendar/skins/default/images/freebusy-colors.gif
Normal file
BIN
plugins/calendar/skins/default/images/freebusy-colors.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 408 B |
BIN
plugins/calendar/skins/default/images/freebusy-colors.png
Normal file
BIN
plugins/calendar/skins/default/images/freebusy-colors.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 631 B |
Loading…
Add table
Reference in a new issue