Fix various calendar regressions

This commit is contained in:
Aleksander Machniak 2019-02-06 09:45:58 +01:00
parent 6cd46fedcf
commit 11ff8f71ea
8 changed files with 143 additions and 94 deletions

View file

@ -1898,9 +1898,6 @@ class calendar extends rcube_plugin
unset($event['allday']);
$event['className'] = $event['className'] ? explode(' ', $event['className']) : array();
if ($addcss) {
$event['className'][] = 'fc-event-cal-' . asciiwords($event['calendar'], true);
}
if ($event['allDay']) {
$event['end'] = $event['end']->add(new DateInterval('P1D'));

View file

@ -162,6 +162,7 @@ function rcube_calendar_ui(settings)
element.addClass('cal-event-status-' + String(event.status).toLowerCase());
}
set_event_colors(element, event, view.name);
element.attr('aria-label', event.title + ', ' + me.event_date_text(event, true));
},
// callback when a specific event is clicked
@ -283,6 +284,50 @@ function rcube_calendar_ui(settings)
return date.getHours() >= settings['work_start'] && date.getHours() < settings['work_end'];
};
var set_event_colors = function(element, event, mode)
{
var bg_color = '', border_color = '',
cat = String(event.categories),
color = event.calendar && me.calendars[event.calendar] ? me.calendars[event.calendar].color : '',
cat_color = rcmail.env.calendar_categories[cat] ? rcmail.env.calendar_categories[cat] : color;
switch (settings.event_coloring) {
case 1:
bg_color = border_color = cat_color;
break;
case 2:
border_color = color;
bg_color = cat_color;
break;
case 3:
border_color = cat_color;
bg_color = color;
break;
default:
bg_color = border_color = color;
break;
}
var css = {
'border-color': border_color,
'background-color': bg_color,
'color': me.text_color(bg_color)
};
if (String(css['border-color']).match(/^#?f+$/i))
delete css['border-color'];
$.each(css, function(i, v) { if (!v) delete css[i]; if (v.charAt(0) != '#') css[i] = '#' + v; });
if (mode == 'list') {
bg_color = css['background-color'];
if (bg_color && !bg_color.match(/^#?f+$/i))
$(element).find('.fc-event-dot').css('background-color', bg_color);
}
else
$(element).css(css);
};
var load_attachment = function(data)
{
var event = data.record,
@ -340,24 +385,17 @@ function rcube_calendar_ui(settings)
$dialog.find('div.event-section, div.event-line, .form-group').hide();
$('#event-title').html(Q(event.title)).show();
if (event.location)
$('#event-location').html('@ ' + text2html(event.location)).show();
if (event.description)
$('#event-description').show().find('.event-text').html(text2html(event.description, 300, 6));
if (event.vurl)
$('#event-url').show().find('.event-text').html(render_link(event.vurl));
// render from-to in a nice human-readable way
// -> now shown in dialog title
// $('#event-date').html(Q(me.event_date_text(event))).show();
if (event.recurrence && event.recurrence_text)
$('#event-repeat').show().find('.event-text').html(Q(event.recurrence_text));
if (event.valarms && event.alarms_text)
$('#event-alarm').show().find('.event-text').html(Q(event.alarms_text).replace(',', ',<br>'));
if (calendar.name)
$('#event-calendar').show().find('.event-text').text(calendar.name).addClass('cal-'+calendar.id);
if (event.categories)
@ -2496,7 +2534,7 @@ function rcube_calendar_ui(settings)
event.editable = false;
event.temp = true;
event.className = ['fc-event-cal-'+data.calendar, 'fc-event-temp'];
event.className = ['fc-event-temp'];
fc.fullCalendar(data.id ? 'updateEvent' : 'renderEvent', event);
@ -3408,28 +3446,13 @@ function rcube_calendar_ui(settings)
// register the given calendar to the current view
var add_calendar_source = function(cal)
{
var color, brightness, select, id = cal.id;
var brightness, select, id = cal.id;
me.calendars[id] = $.extend({
url: rcmail.url('calendar/load_events', { source: id }),
className: ['fc-event-cal-' + id],
id: id
}, cal);
// choose black text color when background is bright, white otherwise
if (color = settings.event_coloring % 2 ? '' : '#' + cal.color) {
me.calendars[id].color = color;
me.calendars[id].textColor = 'white';
if (/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i.test(color)) {
// use information about brightness calculation found at
// http://javascriptrules.com/2009/08/05/css-color-brightness-contrast-using-javascript/
brightness = (parseInt(RegExp.$1, 16) * 299 + parseInt(RegExp.$2, 16) * 587 + parseInt(RegExp.$3, 16) * 114) / 1000;
if (brightness > 125)
me.calendars[id].textColor = '#222';
}
}
if (fc && (cal.active || cal.subscribed)) {
if (cal.active)
fc.fullCalendar('addEventSource', me.calendars[id]);
@ -3648,7 +3671,6 @@ function rcube_calendar_ui(settings)
if (rcmail.env.itip_events && rcmail.env.itip_events.length) {
me.calendars['--invitation--itip'] = {
events: rcmail.env.itip_events,
className: ['fc-event-cal---invitation--itip'],
color: '#fff',
textColor: '#333',
editable: false,
@ -3750,6 +3772,7 @@ function rcube_calendar_ui(settings)
},
viewRender: function(view, element) {
$('#agendaoptions')[view.name == 'list' ? 'show' : 'hide']();
if (minical) {
window.setTimeout(function(){ minical.datepicker('setDate', fc.fullCalendar('getDate').toDate()); }, exec_deferred);
if (view.name != current_view)
@ -3758,16 +3781,20 @@ function rcube_calendar_ui(settings)
me.update_state();
}
if (view.name == 'list') {
var viewStart = moment(view.start);
var viewStart = moment(view.start);
$('#calendar .fc-prev-button').off('click').on('click', function() {
$('#calendar .fc-prev-button').off('click').on('click', function() {
if (view.name == 'list')
fc.fullCalendar('gotoDate', viewStart.subtract(settings.agenda_range, 'days'));
});
$('#calendar .fc-next-button').off('click').on('click', function() {
else
fc.fullCalendar('prev');
});
$('#calendar .fc-next-button').off('click').on('click', function() {
if (view.name == 'list')
fc.fullCalendar('gotoDate', viewStart.add(settings.agenda_range, 'days'));
});
}
else
fc.fullCalendar('next');
});
},
eventAfterAllRender: function(view) {
if (view.name == 'list') {

View file

@ -145,41 +145,30 @@ class calendar_ui
*/
function calendar_css($attrib = array())
{
$categories = $this->cal->driver->list_categories();
$js_categories = array();
$mode = $this->rc->config->get('calendar_event_coloring', $this->cal->defaults['calendar_event_coloring']);
$categories = $this->cal->driver->list_categories();
$css = "\n";
$css = "\n";
foreach ((array)$categories as $class => $color) {
if (empty($color))
continue;
$class = 'cat-' . asciiwords(strtolower($class), true);
$css .= ".$class { color: #$color }\n";
if ($mode > 0) {
if ($mode == 2) {
$css .= ".fc-event-$class .fc-event-bg {";
$css .= " opacity: 0.9;";
$css .= " filter: alpha(opacity=90);";
}
else {
$css .= ".fc-event-$class.fc-event-skin, ";
$css .= ".fc-event-$class .fc-event-skin, ";
$css .= ".fc-event-$class .fc-event-inner {";
}
$css .= " background-color: #" . $color . ";";
if ($mode % 2)
$css .= " border-color: #$color;";
$css .= "}\n";
if (!empty($color)) {
$js_categories[$class] = $color;
$color = ltrim($color, '#');
$class = 'cat-' . asciiwords(strtolower($class), true);
$css .= ".$class { color: #$color; }\n";
}
}
$this->rc->output->set_env('calendar_categories', $js_categories);
$calendars = $this->cal->driver->list_calendars();
foreach ((array)$calendars as $id => $prop) {
if (!$prop['color'])
continue;
$css .= $this->calendar_css_classes($id, $prop, $mode, $attrib);
if ($prop['color']) {
$css .= $this->calendar_css_classes($id, $prop, $mode, $attrib);
}
}
return html::tag('style', array('type' => 'text/css'), $css);
}
@ -192,29 +181,12 @@ class calendar_ui
// replace white with skin-defined color
if (!empty($attrib['folder-fallback-color']) && preg_match('/^f+$/i', $folder_color)) {
$folder_color = $attrib['folder-fallback-color'];
$folder_color = ltrim($attrib['folder-fallback-color'], '#');
}
$class = 'cal-' . asciiwords($id, true);
$css = str_replace('$class', $class, $attrib['folder-class']) ?: "li .$class";
$css .= ", #eventshow .$class { color: #$folder_color; }\n";
if ($mode != 1) {
if ($mode == 3) {
$css .= ".fc-event-$class .fc-event-bg {";
$css .= " opacity: 0.9;";
$css .= " filter: alpha(opacity=90);";
}
else {
$css .= ".fc-event-$class, ";
$css .= ".fc-event-$class .fc-event-inner {";
}
if (!$prop['printmode'])
$css .= " background-color: #$color;";
if ($mode % 2 == 0)
$css .= " border-color: #$color;";
$css .= "}\n";
}
$css .= " { color: #$folder_color; }\n";
return $css . ".$class .handle { background-color: #$color; }\n";
}

View file

@ -55,7 +55,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
source.color = '#' + source.color.replace(/^#/, '');
if (source.color == '#ffffff')
if (source.color.match(/^#f+$/i))
source.color = '#ccc';
event_sources.push(source);

View file

@ -54,10 +54,10 @@
<div id="searchcontrols" class="search-controls"></div>
</div>
<div class="footer toolbar content-frame-navigation" role="toolbar" data-hidden="big">
<a href="#" class="button prev" onclick="$('.fc-button-prev').click()"><span class="inner"><roundcube:label name="previous" /></span></a>
<a href="#" class="button today" onclick="$('.fc-button-today').click()"><span class="inner"><roundcube:label name="today" /></span></a>
<a href="#" class="button prev" onclick="$('.fc-prev-button').click()"><span class="inner"><roundcube:label name="previous" /></span></a>
<a href="#" class="button today" onclick="$('.fc-today-button').click()"><span class="inner"><roundcube:label name="today" /></span></a>
<a href="#" class="button date" onclick="window.calendar_datepicker()"><span class="inner"><roundcube:label name="date" /></span></a>
<a href="#" class="button next" onclick="$('.fc-button-next').click()"><span class="inner"><roundcube:label name="next" /></span></a>
<a href="#" class="button next" onclick="$('.fc-next-button').click()"><span class="inner"><roundcube:label name="next" /></span></a>
</div>
</div>

View file

@ -1828,8 +1828,7 @@ a.dropdown-link:after {
}
.fc-event .fc-bg {
opacity: 1;
background: unset;
opacity: .15;
margin-top: 14px;
cursor: pointer;
}
@ -1864,6 +1863,12 @@ a.dropdown-link:after {
color: #888;
}
.fc-list-table tr.fc-invitation-tentative .fc-event-dot,
.fc-list-table tr.fc-invitation-declined .fc-event-dot,
.fc-list-table tr.fc-invitation-needs-action .fc-event-dot {
background-color: #aaa;
}
.fc-list-table tr.fc-invitation-tentative td.fc-list-item-title,
.fc-list-table tr.fc-invitation-declined td.fc-list-item-title,
.fc-list-table tr.fc-invitation-needs-action td.fc-list-item-title {

View file

@ -43,6 +43,7 @@ function rcube_libcalendaring(settings)
var me = this;
var gmt_offset = (new Date().getTimezoneOffset() / -60) - (settings.timezone || 0) - (settings.dst || 0);
var client_timezone = new Date().getTimezoneOffset();
var color_map = {};
// general datepicker settings
this.datepicker_settings = {
@ -333,6 +334,33 @@ function rcube_libcalendaring(settings)
return date;
}
/**
* Finds text color for specified background color
*/
this.text_color = function(color)
{
var res = '#222';
if (!color) {
return res;
}
if (!color_map[color]) {
color_map[color] = '#fff';
if (/^#?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i.test(color)) {
// use information about brightness calculation found at
// http://javascriptrules.com/2009/08/05/css-color-brightness-contrast-using-javascript/
brightness = (parseInt(RegExp.$1, 16) * 299 + parseInt(RegExp.$2, 16) * 587 + parseInt(RegExp.$3, 16) * 114) / 1000;
if (brightness > 125) {
color_map[color] = res;
}
}
}
return color_map[color];
}
/**
* Simple plaintext to HTML converter, makig URLs clickable
*/

View file

@ -210,6 +210,7 @@ fieldset.categories .input-group {
@color-calendar-border: @color-layout-border;
@color-calendar-free-bg: fadeout(@color-black-shade-text, 80%);
@color-calendar-today: fadeout(@color-warning, 80%);
@color-event-default: #c00;
.fc {
body.quickview-active & .fc-scroller {
@ -262,7 +263,7 @@ fieldset.categories .input-group {
button {
height: unset;
padding: .375rem .75rem;
padding: .3rem .75rem;
}
button.prev:before {
@ -297,23 +298,38 @@ fieldset.categories .input-group {
}
}
.fc-event-dot {
background-color: @color-event-default;
}
a.fc-event, a.fc-event:hover {
color: #fff;
}
.fc-event {
font-size: 1rem;
font-size: 13px;
background-color: @color-event-default;
border-color: @color-event-default;
.fc-title {
font-weight: bold;
}
.fc-bg {
opacity: .15;
margin-top: 1.1rem;
}
&.fc-invitation-needs-action {
border: 1px dashed #5757c7 !important;
border: 1px dashed #5757c7;
}
&.fc-invitation-tentative {
border: 1px dashed #eb8900 !important;
border: 1px dashed #eb8900;
}
&.fc-invitation-declined {
border: 1px dashed #c00 !important;
border: 1px dashed #c00;
}
&.fc-event-ns-other.fc-invitation-declined {
@ -342,6 +358,10 @@ fieldset.categories .input-group {
tr.fc-invitation-declined,
tr.fc-invitation-needs-action {
color: #888;
.fc-event-dot {
background-color: #888;
}
}
}