Fix handling of kolab_freebusy_server=false (and other empty values)

- Cleanup code
- Hide availability features in the Resources tab
This commit is contained in:
Aleksander Machniak 2023-06-23 14:38:10 +02:00
parent 5863bcc947
commit 83d5c9f7f5
6 changed files with 88 additions and 68 deletions

View file

@ -342,6 +342,7 @@ class calendar extends rcube_plugin
$this->rc->output->set_env('timezone', $this->timezone->getName()); $this->rc->output->set_env('timezone', $this->timezone->getName());
$this->rc->output->set_env('calendar_driver', $this->rc->config->get('calendar_driver'), false); $this->rc->output->set_env('calendar_driver', $this->rc->config->get('calendar_driver'), false);
$this->rc->output->set_env('calendar_resources', (bool)$this->rc->config->get('calendar_resources_driver')); $this->rc->output->set_env('calendar_resources', (bool)$this->rc->config->get('calendar_resources_driver'));
$this->rc->output->set_env('calendar_resources_freebusy', !empty($this->rc->config->get('kolab_freebusy_server')));
$this->rc->output->set_env('identities-selector', $this->ui->identity_select([ $this->rc->output->set_env('identities-selector', $this->ui->identity_select([
'id' => 'edit-identities-list', 'id' => 'edit-identities-list',
'aria-label' => $this->gettext('roleorganizer'), 'aria-label' => $this->gettext('roleorganizer'),

View file

@ -924,13 +924,19 @@ function rcube_calendar_ui(settings)
$('#edit-tab-attachments')[(calendar.attachments?'show':'hide')](); $('#edit-tab-attachments')[(calendar.attachments?'show':'hide')]();
$('#eventedit:not([data-notabs])').tabs('option', 'active', 0); // Larry $('#eventedit:not([data-notabs])').tabs('option', 'active', 0); // Larry
// show/hide tabs according to calendar's feature support and activate first tab (Ellastic) // show/hide tabs according to calendar's feature support and activate first tab (Elastic)
$('li > a[href="#event-panel-attendees"]').parent()[(calendar.attendees?'show':'hide')](); $('li > a[href="#event-panel-attendees"]').parent()[(calendar.attendees?'show':'hide')]();
$('li > a[href="#event-panel-resources"]').parent()[(rcmail.env.calendar_resources?'show':'hide')](); $('li > a[href="#event-panel-resources"]').parent()[(rcmail.env.calendar_resources?'show':'hide')]();
$('li > a[href="#event-panel-attachments"]').parent()[(calendar.attachments?'show':'hide')](); $('li > a[href="#event-panel-attachments"]').parent()[(calendar.attachments?'show':'hide')]();
if ($('#eventedit').data('notabs')) if ($('#eventedit').data('notabs'))
$('#eventedit li.nav-item:first-child a').tab('show'); $('#eventedit li.nav-item:first-child a').tab('show');
if (!rcmail.env.calendar_resources_freebusy) {
// With no freebusy setup, some features needs to be hidden
// TODO: Show "Find resources" dialog, but with Availability tab hidden
$('#event-panel-resources').find('#edit-resource-find,#edit-attendees-legend,td.availability,th.availability').hide();
}
// hack: set task to 'calendar' to make all dialog actions work correctly // hack: set task to 'calendar' to make all dialog actions work correctly
var comm_path_before = rcmail.env.comm_path; var comm_path_before = rcmail.env.comm_path;
rcmail.env.comm_path = comm_path_before.replace(/_task=[a-z]+/, '_task=calendar'); rcmail.env.comm_path = comm_path_before.replace(/_task=[a-z]+/, '_task=calendar');
@ -1182,13 +1188,13 @@ function rcube_calendar_ui(settings)
{ {
var $dialog = $('#eventfreebusy'), var $dialog = $('#eventfreebusy'),
event = me.selected_event; event = me.selected_event;
if ($dialog.is(':ui-dialog')) if ($dialog.is(':ui-dialog'))
$dialog.dialog('close'); $dialog.dialog('close');
if (!event_attendees.length) if (!event_attendees.length)
return false; return false;
// set form elements // set form elements
var allday = $('#edit-allday').get(0); var allday = $('#edit-allday').get(0);
var end = 'toDate' in event.end ? event.end : moment(event.end); var end = 'toDate' in event.end ? event.end : moment(event.end);
@ -1199,7 +1205,7 @@ function rcube_calendar_ui(settings)
freebusy_ui.starttime = $('#schedule-starttime').val(format_date(start, settings.time_format)).show(); freebusy_ui.starttime = $('#schedule-starttime').val(format_date(start, settings.time_format)).show();
freebusy_ui.enddate = $('#schedule-enddate').val(format_date(end, settings.date_format)); freebusy_ui.enddate = $('#schedule-enddate').val(format_date(end, settings.date_format));
freebusy_ui.endtime = $('#schedule-endtime').val(format_date(end, settings.time_format)).show(); freebusy_ui.endtime = $('#schedule-endtime').val(format_date(end, settings.time_format)).show();
if (allday.checked) { if (allday.checked) {
freebusy_ui.starttime.val("12:00").hide(); freebusy_ui.starttime.val("12:00").hide();
freebusy_ui.endtime.val("13:00").hide(); freebusy_ui.endtime.val("13:00").hide();
@ -1211,7 +1217,7 @@ function rcube_calendar_ui(settings)
fb_start.setTime(event.start); fb_start.setTime(event.start);
fb_start.setHours(0); fb_start.setMinutes(0); fb_start.setSeconds(0); fb_start.setMilliseconds(0); fb_start.setHours(0); fb_start.setMinutes(0); fb_start.setSeconds(0); fb_start.setMilliseconds(0);
fb_end.setTime(fb_start.getTime() + DAY_MS); fb_end.setTime(fb_start.getTime() + DAY_MS);
freebusy_data = { required:{}, all:{} }; freebusy_data = { required:{}, all:{} };
freebusy_ui.loading = 1; // prevent render_freebusy_grid() to load data yet freebusy_ui.loading = 1; // prevent render_freebusy_grid() to load data yet
freebusy_ui.numdays = Math.max(allday.checked ? 14 : 1, Math.ceil(duration * 2 / 86400)); freebusy_ui.numdays = Math.max(allday.checked ? 14 : 1, Math.ceil(duration * 2 / 86400));
@ -1219,7 +1225,7 @@ function rcube_calendar_ui(settings)
freebusy_ui.start = fb_start; freebusy_ui.start = fb_start;
freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays); freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays);
render_freebusy_grid(0); render_freebusy_grid(0);
// render list of attendees // render list of attendees
freebusy_ui.attendees = {}; freebusy_ui.attendees = {};
var domid, dispname, data, role_html, list_html = ''; var domid, dispname, data, role_html, list_html = '';
@ -1229,15 +1235,15 @@ function rcube_calendar_ui(settings)
domid = String(data.email).replace(rcmail.identifier_expr, ''); domid = String(data.email).replace(rcmail.identifier_expr, '');
role_html = '<a class="attendee-role-toggle" id="rcmlia' + domid + '" title="' + Q(rcmail.gettext('togglerole', 'calendar')) + '">&nbsp;</a>'; role_html = '<a class="attendee-role-toggle" id="rcmlia' + domid + '" title="' + Q(rcmail.gettext('togglerole', 'calendar')) + '">&nbsp;</a>';
list_html += '<div class="attendee ' + String(data.role).toLowerCase() + '" id="rcmli' + domid + '">' + role_html + dispname + '</div>'; list_html += '<div class="attendee ' + String(data.role).toLowerCase() + '" id="rcmli' + domid + '">' + role_html + dispname + '</div>';
// clone attendees data for local modifications // clone attendees data for local modifications
freebusy_ui.attendees[i] = freebusy_ui.attendees[domid] = $.extend({}, data); freebusy_ui.attendees[i] = freebusy_ui.attendees[domid] = $.extend({}, data);
} }
// add total row // add total row
list_html += '<div class="attendee spacer">&nbsp;</div>'; list_html += '<div class="attendee spacer">&nbsp;</div>';
list_html += '<div class="attendee total">' + rcmail.gettext('reqallattendees','calendar') + '</div>'; list_html += '<div class="attendee total">' + rcmail.gettext('reqallattendees','calendar') + '</div>';
$('#schedule-attendees-list').html(list_html) $('#schedule-attendees-list').html(list_html)
.unbind('click.roleicons') .unbind('click.roleicons')
.bind('click.roleicons', function(e) { .bind('click.roleicons', function(e) {
@ -1251,7 +1257,7 @@ function rcube_calendar_ui(settings)
j = (j+1) % roles.length; j = (j+1) % roles.length;
attendee.role = roles[j]; attendee.role = roles[j];
$(e.target).parent().attr('class', 'attendee '+String(attendee.role).toLowerCase()); $(e.target).parent().attr('class', 'attendee '+String(attendee.role).toLowerCase());
// update total display if required-status changed // update total display if required-status changed
if (req != (roles[j] != 'OPT-PARTICIPANT' && roles[j] != 'NON-PARTICIPANT')) { if (req != (roles[j] != 'OPT-PARTICIPANT' && roles[j] != 'NON-PARTICIPANT')) {
compute_freebusy_totals(); compute_freebusy_totals();
@ -1259,7 +1265,7 @@ function rcube_calendar_ui(settings)
} }
} }
} }
return false; return false;
}); });
@ -1321,12 +1327,12 @@ function rcube_calendar_ui(settings)
minWidth: 640, minWidth: 640,
width: 850 width: 850
}).show(); }).show();
// adjust dialog size to fit grid without scrolling // adjust dialog size to fit grid without scrolling
var gridw = $('#schedule-freebusy-times').width(); var gridw = $('#schedule-freebusy-times').width();
var overflow = gridw - $('#attendees-freebusy-table td.times').width(); var overflow = gridw - $('#attendees-freebusy-table td.times').width();
me.dialog_resize($dialog.get(0), $dialog.height() + (bw.ie ? 20 : 0), 800 + Math.max(0, overflow)); me.dialog_resize($dialog.get(0), $dialog.height() + (bw.ie ? 20 : 0), 800 + Math.max(0, overflow));
// fetch data from server // fetch data from server
freebusy_ui.loading = 0; freebusy_ui.loading = 0;
load_freebusy_data(freebusy_ui.start, freebusy_ui.interval); load_freebusy_data(freebusy_ui.start, freebusy_ui.interval);
@ -1338,17 +1344,17 @@ function rcube_calendar_ui(settings)
if (delta) { if (delta) {
freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta); freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta);
fix_date(freebusy_ui.start); fix_date(freebusy_ui.start);
// skip weekends if in workinhoursonly-mode // skip weekends if in workinhoursonly-mode
if (Math.abs(delta) == 1 && freebusy_ui.workinhoursonly) { if (Math.abs(delta) == 1 && freebusy_ui.workinhoursonly) {
while (is_weekend(freebusy_ui.start)) while (is_weekend(freebusy_ui.start))
freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta); freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta);
fix_date(freebusy_ui.start); fix_date(freebusy_ui.start);
} }
freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays); freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays);
} }
var dayslots = Math.floor(1440 / freebusy_ui.interval); var dayslots = Math.floor(1440 / freebusy_ui.interval);
var date_format = 'ddd '+ (dayslots <= 2 ? settings.date_short : settings.date_format); var date_format = 'ddd '+ (dayslots <= 2 ? settings.date_short : settings.date_format);
var lastdate, datestr, css, var lastdate, datestr, css,
@ -1368,17 +1374,17 @@ function rcube_calendar_ui(settings)
dates_row += '<th colspan="' + dayslots + '" class="boxtitle date' + format_date(curdate, 'DDMMYYYY') + '">' + Q(datestr) + '</th>'; dates_row += '<th colspan="' + dayslots + '" class="boxtitle date' + format_date(curdate, 'DDMMYYYY') + '">' + Q(datestr) + '</th>';
lastdate = datestr; lastdate = datestr;
} }
// set css class according to working hours // set css class according to working hours
css = is_weekend(curdate) || (freebusy_ui.interval <= 60 && !is_workinghour(curdate)) ? 'offhours' : 'workinghours'; css = is_weekend(curdate) || (freebusy_ui.interval <= 60 && !is_workinghour(curdate)) ? 'offhours' : 'workinghours';
times_row += '<td class="' + times_css + css + '" id="t-' + Math.floor(t/1000) + '">' + Q(allday ? rcmail.gettext('all-day','calendar') : format_date(curdate, settings.time_format)) + '</td>'; times_row += '<td class="' + times_css + css + '" id="t-' + Math.floor(t/1000) + '">' + Q(allday ? rcmail.gettext('all-day','calendar') : format_date(curdate, settings.time_format)) + '</td>';
slots_row += '<td class="' + css + '">&nbsp;</td>'; slots_row += '<td class="' + css + '">&nbsp;</td>';
t += interval * 60000; t += interval * 60000;
} }
dates_row += '</tr>'; dates_row += '</tr>';
times_row += '</tr>'; times_row += '</tr>';
// render list of attendees // render list of attendees
var domid, data, list_html = '', times_html = ''; var domid, data, list_html = '', times_html = '';
for (var i=0; i < event_attendees.length; i++) { for (var i=0; i < event_attendees.length; i++) {
@ -1386,15 +1392,15 @@ function rcube_calendar_ui(settings)
domid = String(data.email).replace(rcmail.identifier_expr, ''); domid = String(data.email).replace(rcmail.identifier_expr, '');
times_html += '<tr id="fbrow' + domid + '" class="fbcontent">' + slots_row + '</tr>'; times_html += '<tr id="fbrow' + domid + '" class="fbcontent">' + slots_row + '</tr>';
} }
// add line for all/required attendees // add line for all/required attendees
times_html += '<tr class="spacer"><td colspan="' + (dayslots * freebusy_ui.numdays) + '"></td>'; times_html += '<tr class="spacer"><td colspan="' + (dayslots * freebusy_ui.numdays) + '"></td>';
times_html += '<tr id="fbrowall" class="fbcontent">' + slots_row + '</tr>'; times_html += '<tr id="fbrowall" class="fbcontent">' + slots_row + '</tr>';
var table = $('#schedule-freebusy-times'); var table = $('#schedule-freebusy-times');
table.children('thead').html(dates_row + times_row); table.children('thead').html(dates_row + times_row);
table.children('tbody').html(times_html); table.children('tbody').html(times_html);
// initialize event handlers on grid // initialize event handlers on grid
if (!freebusy_ui.grid_events) { if (!freebusy_ui.grid_events) {
freebusy_ui.grid_events = true; freebusy_ui.grid_events = true;
@ -1412,7 +1418,7 @@ function rcube_calendar_ui(settings)
} }
}); });
} }
// if we have loaded free-busy data, show it // if we have loaded free-busy data, show it
if (!freebusy_ui.loading) { if (!freebusy_ui.loading) {
if (freebusy_ui.start < freebusy_data.start || freebusy_ui.end > freebusy_data.end || freebusy_ui.interval != freebusy_data.interval) { if (freebusy_ui.start < freebusy_data.start || freebusy_ui.end > freebusy_data.end || freebusy_ui.interval != freebusy_data.interval) {
@ -1425,12 +1431,12 @@ function rcube_calendar_ui(settings)
} }
} }
} }
// render current event date/time selection over grid table // render current event date/time selection over grid table
// use timeout to let the dom attributes (width/height/offset) be set first // use timeout to let the dom attributes (width/height/offset) be set first
window.setTimeout(function(){ render_freebusy_overlay(); }, 10); window.setTimeout(function(){ render_freebusy_overlay(); }, 10);
}; };
// render overlay element over the grid to visiualize the current event date/time // render overlay element over the grid to visiualize the current event date/time
var render_freebusy_overlay = function() var render_freebusy_overlay = function()
{ {
@ -1549,7 +1555,7 @@ function rcube_calendar_ui(settings)
domid = String(email).replace(rcmail.identifier_expr, ''); domid = String(email).replace(rcmail.identifier_expr, '');
$('#rcmli' + domid).addClass('loading'); $('#rcmli' + domid).addClass('loading');
freebusy_ui.loading++; freebusy_ui.loading++;
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
dataType: 'json', dataType: 'json',
@ -1557,7 +1563,7 @@ function rcube_calendar_ui(settings)
data: { email:email, start:date2servertime(clone_date(start, 1)), end:date2servertime(clone_date(end, 2)), interval:interval, _remote:1 }, data: { email:email, start:date2servertime(clone_date(start, 1)), end:date2servertime(clone_date(end, 2)), interval:interval, _remote:1 },
success: function(data) { success: function(data) {
freebusy_ui.loading--; freebusy_ui.loading--;
// find attendee // find attendee
var i, attendee = null; var i, attendee = null;
for (i=0; i < event_attendees.length; i++) { for (i=0; i < event_attendees.length; i++) {
@ -1566,7 +1572,7 @@ function rcube_calendar_ui(settings)
break; break;
} }
} }
// copy data to member var // copy data to member var
var ts, status, var ts, status,
req = attendee.role != 'OPT-PARTICIPANT', req = attendee.role != 'OPT-PARTICIPANT',
@ -1582,13 +1588,13 @@ function rcube_calendar_ui(settings)
status = data.slots.charAt(i); status = data.slots.charAt(i);
freebusy_data[data.email][ts] = status freebusy_data[data.email][ts] = status
start = new Date(start.getTime() + data.interval * 60000); start = new Date(start.getTime() + data.interval * 60000);
// set totals // set totals
if (!freebusy_data.required[ts]) if (!freebusy_data.required[ts])
freebusy_data.required[ts] = [0,0,0,0]; freebusy_data.required[ts] = [0,0,0,0];
if (req) if (req)
freebusy_data.required[ts][status]++; freebusy_data.required[ts][status]++;
if (!freebusy_data.all[ts]) if (!freebusy_data.all[ts])
freebusy_data.all[ts] = [0,0,0,0]; freebusy_data.all[ts] = [0,0,0,0];
freebusy_data.all[ts][status]++; freebusy_data.all[ts][status]++;
@ -1597,44 +1603,44 @@ function rcube_calendar_ui(settings)
// hide loading indicator // hide loading indicator
var domid = String(data.email).replace(rcmail.identifier_expr, ''); var domid = String(data.email).replace(rcmail.identifier_expr, '');
$('#rcmli' + domid).removeClass('loading'); $('#rcmli' + domid).removeClass('loading');
// update display // update display
update_freebusy_display(data.email); update_freebusy_display(data.email);
} }
}); });
// count required attendees // count required attendees
if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT') if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT')
freebusy_ui.numrequired++; freebusy_ui.numrequired++;
} }
} }
}; };
// re-calculate total status after role change // re-calculate total status after role change
var compute_freebusy_totals = function() var compute_freebusy_totals = function()
{ {
freebusy_ui.numrequired = 0; freebusy_ui.numrequired = 0;
freebusy_data.all = []; freebusy_data.all = [];
freebusy_data.required = []; freebusy_data.required = [];
var email, req, status; var email, req, status;
for (var i=0; i < event_attendees.length; i++) { for (var i=0; i < event_attendees.length; i++) {
if (!(email = event_attendees[i].email)) if (!(email = event_attendees[i].email))
continue; continue;
req = freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT'; req = freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT';
if (req) if (req)
freebusy_ui.numrequired++; freebusy_ui.numrequired++;
for (var ts in freebusy_data[email]) { for (var ts in freebusy_data[email]) {
if (!freebusy_data.required[ts]) if (!freebusy_data.required[ts])
freebusy_data.required[ts] = [0,0,0,0]; freebusy_data.required[ts] = [0,0,0,0];
if (!freebusy_data.all[ts]) if (!freebusy_data.all[ts])
freebusy_data.all[ts] = [0,0,0,0]; freebusy_data.all[ts] = [0,0,0,0];
status = freebusy_data[email][ts]; status = freebusy_data[email][ts];
freebusy_data.all[ts][status]++; freebusy_data.all[ts][status]++;
if (req) if (req)
freebusy_data.required[ts][status]++; freebusy_data.required[ts][status]++;
} }
@ -1787,7 +1793,7 @@ function rcube_calendar_ui(settings)
break; break;
} }
} }
// occupied slot // occupied slot
if (!candidatestart) { if (!candidatestart) {
slot += Math.max(0, intvlslots - candidatecount - 1) * sinterval * dir; slot += Math.max(0, intvlslots - candidatecount - 1) * sinterval * dir;
@ -1796,9 +1802,9 @@ function rcube_calendar_ui(settings)
} }
else if (dir < 0) else if (dir < 0)
candidatestart = slot; candidatestart = slot;
candidatecount++; candidatecount++;
// if candidate is big enough, this is it! // if candidate is big enough, this is it!
if (candidatecount == numslots) { if (candidatecount == numslots) {
'toDate' in event.start ? (event.start = new Date(candidatestart)) : event.start.setTime(candidatestart); 'toDate' in event.start ? (event.start = new Date(candidatestart)) : event.start.setTime(candidatestart);
@ -1859,7 +1865,7 @@ function rcube_calendar_ui(settings)
for (var i=0; i < names.length; i++) { for (var i=0; i < names.length; i++) {
email = name = ''; email = name = '';
item = $.trim(names[i]); item = $.trim(names[i]);
if (!item.length) { if (!item.length) {
continue; continue;
} // address in brackets without name (do nothing) } // address in brackets without name (do nothing)
@ -1881,7 +1887,7 @@ function rcube_calendar_ui(settings)
rcmail.alert_dialog(rcmail.gettext('noemailwarning')); rcmail.alert_dialog(rcmail.gettext('noemailwarning'));
} }
} }
return success; return success;
}; };
@ -2006,10 +2012,10 @@ function rcube_calendar_ui(settings)
if (email = icon.attr('data-email')) if (email = icon.attr('data-email'))
check_freebusy_status(icon, email, event); check_freebusy_status(icon, email, event);
}); });
freebusy_ui.needsupdate = false; freebusy_ui.needsupdate = false;
}; };
// load free-busy status from server and update icon accordingly // load free-busy status from server and update icon accordingly
var check_freebusy_status = function(icon, email, event) var check_freebusy_status = function(icon, email, event)
{ {
@ -2018,9 +2024,9 @@ function rcube_calendar_ui(settings)
$(icon).attr('class', 'availabilityicon unknown'); $(icon).attr('class', 'availabilityicon unknown');
return; return;
} }
icon = $(icon).attr('class', 'availabilityicon loading'); icon = $(icon).attr('class', 'availabilityicon loading');
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
dataType: 'html', dataType: 'html',
@ -2035,7 +2041,7 @@ function rcube_calendar_ui(settings)
} }
}); });
}; };
// remove an attendee from the list // remove an attendee from the list
var remove_attendee = function(elem, id) var remove_attendee = function(elem, id)
{ {
@ -3369,20 +3375,21 @@ function rcube_calendar_ui(settings)
if (q != '') { if (q != '') {
var id = 'search-'+q; var id = 'search-'+q;
var sources = []; var sources = [];
if (me.quickview_active) if (me.quickview_active)
reset_quickview(); reset_quickview();
if (this._search_message) if (this._search_message)
rcmail.hide_message(this._search_message); rcmail.hide_message(this._search_message);
$.each(fc.fullCalendar('getEventSources'), function() { $.each(fc.fullCalendar('getEventSources'), function() {
this.url = this.url.replace(/&q=.+/, '') + '&q=' + urlencode(q); this.url = this.url.replace(/&q=.+/, '') + '&q=' + urlencode(q);
me.calendars[this.id].url = this.url; me.calendars[this.id].url = this.url;
sources.push(this.id); sources.push(this.id);
}); });
id += '@'+sources.join(','); id += '@'+sources.join(',');
// ignore if query didn't change // ignore if query didn't change
if (this.search_request == id) { if (this.search_request == id) {
return; return;
@ -3391,10 +3398,10 @@ function rcube_calendar_ui(settings)
else if (!this.search_request) { else if (!this.search_request) {
this.default_view = fc.fullCalendar('getView').name; this.default_view = fc.fullCalendar('getView').name;
} }
this.search_request = id; this.search_request = id;
this.search_query = q; this.search_query = q;
// change to list view // change to list view
fc.fullCalendar('changeView', 'list'); fc.fullCalendar('changeView', 'list');

View file

@ -2016,6 +2016,12 @@ class kolab_driver extends calendar_driver
return false; return false;
} }
$url = $this->storage->get_freebusy_url($email);
if (empty($url)) {
return false;
}
// map vcalendar fbtypes to internal values // map vcalendar fbtypes to internal values
$fbtypemap = [ $fbtypemap = [
'FREE' => calendar::FREEBUSY_FREE, 'FREE' => calendar::FREEBUSY_FREE,
@ -2031,7 +2037,7 @@ class kolab_driver extends calendar_driver
'follow_redirects' => true, 'follow_redirects' => true,
]; ];
$request = libkolab::http_request($this->storage->get_freebusy_url($email), 'GET', $request_config); $request = libkolab::http_request($url, 'GET', $request_config);
$response = $request->send(); $response = $request->send();
// authentication required // authentication required

View file

@ -279,11 +279,12 @@ class kolab_storage
{ {
$rcmail = rcube::get_instance(); $rcmail = rcube::get_instance();
$url = 'https://' . $_SESSION['imap_host'] . '/freebusy'; if ($url = $rcmail->config->get('kolab_freebusy_server')) {
$url = $rcmail->config->get('kolab_freebusy_server', $url); $url = rcube_utils::resolve_url($url);
$url = rcube_utils::resolve_url($url); $url = unslashify($url);
}
return unslashify($url); return $url;
} }
/** /**
@ -293,10 +294,16 @@ class kolab_storage
* @param object DateTime Start of the query range (optional) * @param object DateTime Start of the query range (optional)
* @param object DateTime End of the query range (optional) * @param object DateTime End of the query range (optional)
* *
* @return string Fully qualified URL to query free/busy data * @return ?string Fully qualified URL to query free/busy data
*/ */
public static function get_freebusy_url($email, $start = null, $end = null) public static function get_freebusy_url($email, $start = null, $end = null)
{ {
$url = self::get_freebusy_server();
if (empty($url)) {
return null;
}
$query = ''; $query = '';
$param = array(); $param = array();
$utc = new \DateTimeZone('UTC'); $utc = new \DateTimeZone('UTC');
@ -317,8 +324,6 @@ class kolab_storage
$query = '?' . http_build_query($param); $query = '?' . http_build_query($param);
} }
$url = self::get_freebusy_server();
if (strpos($url, '%u')) { if (strpos($url, '%u')) {
// Expected configured full URL, just replace the %u variable // Expected configured full URL, just replace the %u variable
// Note: Cyrus v3 Free-Busy service does not use .ifb extension // Note: Cyrus v3 Free-Busy service does not use .ifb extension

View file

@ -149,7 +149,7 @@ class kolab_storage_dav
* @param object DateTime Start of the query range (optional) * @param object DateTime Start of the query range (optional)
* @param object DateTime End of the query range (optional) * @param object DateTime End of the query range (optional)
* *
* @return string Fully qualified URL to query free/busy data * @return ?string Fully qualified URL to query free/busy data
*/ */
public static function get_freebusy_url($email, $start = null, $end = null) public static function get_freebusy_url($email, $start = null, $end = null)
{ {

View file

@ -1099,13 +1099,14 @@ class kolab_storage_folder extends kolab_storage_folder_api
{ {
$owner = $this->get_owner(); $owner = $this->get_owner();
$result = false; $result = false;
$url = kolab_storage::get_freebusy_server();
switch($this->type) { switch ($this->type) {
case 'event': case 'event':
if ($this->get_namespace() == 'personal') { if ($url && $this->get_namespace() == 'personal') {
$result = $this->trigger_url( $result = $this->trigger_url(
sprintf('%s/trigger/%s/%s.pfb', sprintf('%s/trigger/%s/%s.pfb',
kolab_storage::get_freebusy_server(), $url,
urlencode($owner), urlencode($owner),
urlencode($this->imap->mod_folder($this->name)) urlencode($this->imap->mod_folder($this->name))
), ),
@ -1119,7 +1120,7 @@ class kolab_storage_folder extends kolab_storage_folder_api
return true; return true;
} }
if ($result && is_object($result) && is_a($result, 'PEAR_Error')) { if ($result instanceof PEAR_Error) {
return PEAR::raiseError( return PEAR::raiseError(
sprintf("Failed triggering folder %s. Error was: %s", $this->name, $result->getMessage()) sprintf("Failed triggering folder %s. Error was: %s", $this->name, $result->getMessage())
); );