Elastic: Calendar - Resources dialog

This commit is contained in:
Aleksander Machniak 2018-04-11 11:44:44 +02:00
parent 91b4bc34d5
commit 3027b61ec2
6 changed files with 178 additions and 66 deletions

View file

@ -2004,7 +2004,7 @@ function rcube_calendar_ui(settings)
{
text: rcmail.gettext('addresource', 'calendar'),
'class': 'mainaction save',
click: function() { rcmail.command('add-resource'); }
click: function() { rcmail.command('add-resource'); $dialog.dialog("close"); }
},
{
text: rcmail.gettext('close'),
@ -2013,23 +2013,33 @@ function rcube_calendar_ui(settings)
}
];
var resize = function() {
var container = $(rcmail.gui_objects.resourceinfocalendar);
container.fullCalendar('option', 'height', container.height() + 1);
};
// open jquery UI dialog
$dialog.dialog({
modal: true,
resizable: true,
resizable: false, // prevents from Availability tab reflow bugs on resize
closeOnEscape: true,
title: rcmail.gettext('findresources', 'calendar'),
classes: {'ui-dialog': 'resources-dialog'},
open: function() {
rcmail.ksearch_blur();
$dialog.attr('aria-hidden', 'false');
// for Elastic
if ($('html.layout-small,html.layout-phone').length) {
$('#eventresourcesdialog .resource-selection').css('display', 'flex');
$('#eventresourcesdialog .resource-content').css('display', 'none');
}
setTimeout(resize, 50);
},
close: function() {
$dialog.dialog('destroy').attr('aria-hidden', 'true').hide();
},
resize: function(e) {
var container = $(rcmail.gui_objects.resourceinfocalendar);
container.fullCalendar('option', 'height', container.height() + 4);
},
resize: resize,
buttons: buttons,
width: 900,
height: 500
@ -2055,6 +2065,14 @@ function rcube_calendar_ui(settings)
if (resources_data[node.id]) {
resource_showinfo(resources_data[node.id]);
rcmail.enable_command('add-resource', me.selected_event && $("#eventedit").is(':visible') ? true : false);
// on elastic mobile display resource info box
if ($('html.layout-small,html.layout-phone').length) {
$('#eventresourcesdialog .resource-selection').css('display', 'none');
$('#eventresourcesdialog .resource-content').css('display', 'flex');
$(window).resize();
resize();
}
}
else {
rcmail.enable_command('add-resource', false);
@ -2130,9 +2148,9 @@ function rcube_calendar_ui(settings)
for (var k in attribs) {
if (typeof attribs[k] == 'undefined')
continue;
table.append($('<tr>').addClass(k)
.append('<td class="title">' + Q(ucfirst(rcmail.get_label(k, 'calendar'))) + '</td>')
.append('<td class="value">' + text2html(render_attrib(attribs[k])) + '</td>')
table.append($('<tr>').addClass(k + ' form-group row')
.append('<td class="title col-sm-4"><label class="col-form-label">' + Q(ucfirst(rcmail.get_label(k, 'calendar'))) + '</label></td>')
.append('<td class="value col-sm-8 form-control-plaintext">' + text2html(render_attrib(attribs[k])) + '</td>')
);
}
@ -4050,12 +4068,17 @@ function rcube_calendar_ui(settings)
input.val('');
}
});
$('#edit-resource-find').click(function(){
event_resources_dialog();
return false;
});
$('#resource-content a.nav-link').on('click', function() {
e.preventDefault();
$(this).tab('show');
});
// handle change of "send invitations" checkbox
$('#edit-attendees-invite').change(function() {
$('#edit-attendees-donotify,input.edit-attendee-reply').prop('checked', this.checked);

View file

@ -234,7 +234,7 @@ class kolab_invitation_calendar
$events = array();
foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
$cal = $this->_get_calendar($foldername);
if ($cal->get_namespace() == 'other')
if (!$cal || $cal->get_namespace() == 'other')
continue;
foreach ($cal->list_events($start, $end, $search, 1, $query, array(array($subquery, 'OR'))) as $event) {
@ -288,7 +288,7 @@ class kolab_invitation_calendar
$count = 0;
foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
$cal = $this->_get_calendar($foldername);
if ($cal->get_namespace() == 'other')
if (!$cal || $cal->get_namespace() == 'other')
continue;
$count += $cal->count_events($start, $end, $filter);

View file

@ -805,20 +805,16 @@ class calendar_ui
*/
function resources_search_form($attrib)
{
$attrib += array('command' => 'search-resource', 'id' => 'rcmcalresqsearchbox', 'autocomplete' => 'off');
$attrib['name'] = '_q';
$input_q = new html_inputfield($attrib);
$out = $input_q->show();
$attrib += array(
'command' => 'search-resource',
'reset-command' => 'reset-resource-search',
'id' => 'rcmcalresqsearchbox',
'autocomplete' => 'off',
'form-name' => 'rcmcalresoursqsearchform',
);
// add form tag around text field
$out = $this->rc->output->form_tag(array(
'name' => "rcmcalresoursqsearchform",
'onsubmit' => rcmail_output::JS_OBJECT_NAME . ".command('" . $attrib['command'] . "'); return false",
'style' => "display:inline"),
$out);
return $out;
return $this->rc->output->search_form($attrib);
}
/**

View file

@ -222,6 +222,7 @@ $labels['addresource'] = 'Book resource';
$labels['findresources'] = 'Find resources';
$labels['resourcedetails'] = 'Details';
$labels['resourceavailability'] = 'Availability';
$labels['resourceprops'] = 'Resource properties';
$labels['resourceowner'] = 'Owner';
$labels['resourceadded'] = 'The resource was added to your event';

View file

@ -183,37 +183,52 @@
</div>
<div id="eventresourcesdialog" class="popupmenu">
<div class="resources-dialog">
<h3 class="voice" id="aria-label-resourceselection"><roundcube:label name="calendar.arialabelresourceselection" /></h3>
<div class="resource-selection uibox listbox" role="navigation" aria-labelledby="aria-label-resourceselection">
<h3 class="voice" id="aria-label-resourceselection"><roundcube:label name="calendar.arialabelresourceselection" /></h3>
<div class="resource-selection " role="navigation" aria-labelledby="aria-label-resourceselection">
<div class="header">
<span class="header-title"><roundcube:label name="calendar.tabresources" /></span>
<div id="resourcequicksearch" class="header">
<div class="searchbox" role="search" aria-labelledby="aria-label-resourcesearchform" aria-controls="resources-list">
<h3 id="aria-label-resourcesearchform" class="voice"><roundcube:label name="calendar.arialabelresourcesearchform" /></h3>
<label for="resourcesearchbox" class="voice"><roundcube:label name="calendar.searchterms" /></label>
<roundcube:object name="plugin.resources_searchform" id="resourcesearchbox" />
<a id="resourcesearchmenulink" class="iconbutton searchoptions"> </a>
<roundcube:button type="link" command="reset-resource-search" id="resourcesearchreset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
</div>
</div>
<div class="scroller">
<roundcube:object name="plugin.resources_list" id="resources-list" class="listing treelist" />
</div>
<roundcube:object name="plugin.resources_searchform" id="resourcesearchbox"
wrapper="searchbar toolbar" ariatag="h4" buttontitle="calendar.findresources"
label="resourcesearchform" label-domain="calendar" />
</div>
<div class="resource-content">
<div id="resource-info" class="uibox contentbox" role="region" aria-labelledby="aria-label-resourcedetails">
<h2 class="boxtitle" id="aria-label-resourcedetails"><roundcube:label name="calendar.resourcedetails" /></h2>
<div class="scroller">
<roundcube:object name="plugin.resource_info" id="resource-details" class="propform" aria-live="polite" aria-relevant="text" aria-atomic="true" />
<div class="scroller">
<roundcube:object name="plugin.resources_list" id="resources-list" class="listing treelist" />
</div>
</div>
<div class="resource-content">
<div class="header" data-hidden="normal,big">
<a class="button icon back" href="#back" onclick="$('#eventresourcesdialog .resource-content').hide(); $('#eventresourcesdialog .resource-selection').show()">
<span class="inner"><roundcube:label name="back" /></span>
</a>
<span class="header-title"><roundcube:label name="calendar.resourceprops" /></span>
</div>
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" href="#resource-availability" data-toggle="tab" role="tab">
<roundcube:label name="calendar.resourceavailability" />
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#resource-info" data-toggle="tab" role="tab">
<roundcube:label name="calendar.resourcedetails" />
</a>
</li>
</ul>
<div class="tab-content">
<div id="resource-availability" class="tab-pane active" role="tabpanel" aria-labelledby="aria-label-resourceavailability">
<h3 class="voice" id="aria-label-resourceavailability"><roundcube:label name="calendar.resourceavailability" /></h3>
<roundcube:object name="plugin.resource_calendar" id="resource-freebusy-calendar" class="raw-tables" />
<div class="slot-nav">
<roundcube:button name="resource-cal-prev" id="resource-calendar-prev" type="link"
class="icon prevpage" title="calendar.prevslot" label="calendar.prevweek" />
<roundcube:button name="resource-cal-next" id="resource-calendar-next" type="link"
class="icon nextpage" title="calendar.nextslot" label="calendar.nextweek" />
</div>
</div>
<div id="resource-availability" class="uibox contentbox" role="region" aria-labelledby="aria-label-resourceavailability">
<h2 class="boxtitle" id="aria-label-resourceavailability"><roundcube:label name="calendar.resourceavailability" /></h2>
<roundcube:object name="plugin.resource_calendar" id="resource-freebusy-calendar" />
<div class="boxpagenav">
<roundcube:button name="resource-cal-prev" id="resource-calendar-prev" type="link" class="icon prevpage" title="calendar.prevslot" label="calendar.prevweek" />
<roundcube:button name="resource-cal-next" id="resource-calendar-next" type="link" class="icon nextpage" title="calendar.nextslot" label="calendar.nextweek" />
</div>
<div id="resource-info" class="tab-pane" role="tabpanel" aria-labelledby="aria-label-resourcedetails">
<h3 class="voice" id="aria-label-resourcedetails"><roundcube:label name="calendar.resourcedetails" /></h3>
<roundcube:object name="plugin.resource_info" id="resource-details" class="propform text-only"
aria-live="polite" aria-relevant="text" aria-atomic="true" />
</div>
</div>
</div>

View file

@ -1640,31 +1640,46 @@ body.task-calendar {
}
.resources-dialog {
display: flex;
height: 100%;
.ui-dialog-content {
display: flex !important;
overflow: hidden !important;
}
.resource-selection {
flex: 4;
display: flex;
flex-direction: column;
border: 1px solid @color-layout-border;
min-width: 300px;
justify-content: center;
.header {
border-bottom: 1px solid @color-layout-border;
display: flex;
background-color: @color-layout-header-background;
font-size: @layout-header-font-size;
font-weight: bold;
line-height: @layout-header-height;
height: @layout-header-height;
min-height: @layout-header-height;
padding: 0 .25em;
position: relative; // for absolute positioning of searchbar
overflow: hidden;
white-space: nowrap;
.scroller {
flex: 1;
overflow-y: auto;
}
}
.header {
border-bottom: 1px solid @color-layout-border;
display: flex;
background-color: @color-layout-header-background;
font-size: @layout-header-font-size;
font-weight: bold;
line-height: @layout-header-height;
height: @layout-header-height;
min-height: @layout-header-height;
padding: 0 .25em;
position: relative; // for absolute positioning of searchbar
overflow: hidden;
white-space: nowrap;
}
.header-title {
width: 100%;
text-align: center;
margin: 0 2em;
}
.resource-content {
flex: 10;
display: flex;
@ -1680,6 +1695,38 @@ body.task-calendar {
content: @fa-var-cube;
}
}
.tab-content {
margin-top: 1rem;
height: 100%;
overflow-y: auto;
}
.slot-nav {
display: none; // TODO
}
}
#resource-availability {
height: 100%;
.fc {
height: 100%;
overflow: hidden;
position: relative;
}
.fc-content {
}
.fc-view {
border-left: 1px solid @color-calendar-border;
border-bottom: 1px solid @color-calendar-border;
}
table.fc-header {
display: none;
}
}
.standalone-invitebox {
@ -1785,6 +1832,36 @@ body.task-calendar {
.sidebar .calendar-datepicker {
display: none;
}
.resources-dialog {
.ui-dialog-content {
padding: 0 !important;
}
.resource-selection {
border: 0;
}
.resource-content,
.ui-dialog-titlebar {
display: none;
margin: 0;
}
.resource-content {
.header-title {
margin-left: 0;
}
ul {
margin: 1em 1em 0 1em;
}
}
}
#resource-availability {
margin: 0 1em;
}
}
@media screen and (max-width: 420px) {