From ea873a9589a11a33ee49f27abf9ac30af9a1690b Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 15 Jan 2019 12:18:21 +0100 Subject: [PATCH] Calendar Agenda and searching fixes --- plugins/calendar/calendar.php | 4 +- plugins/calendar/calendar_ui.js | 193 ++++++++-------------- plugins/calendar/skins/larry/calendar.css | 80 +++++---- plugins/libcalendaring/libcalendaring.php | 8 +- 4 files changed, 117 insertions(+), 168 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 5cfce808..d97d1b5d 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -322,7 +322,7 @@ class calendar extends rcube_plugin ))); $view = rcube_utils::get_input_value('view', rcube_utils::INPUT_GPC); - if (in_array($view, array('agendaWeek', 'agendaDay', 'month', 'table'))) + if (in_array($view, array('agendaWeek', 'agendaDay', 'month', 'list'))) $this->rc->output->set_env('view', $view); if ($date = rcube_utils::get_input_value('date', rcube_utils::INPUT_GPC)) @@ -2421,7 +2421,7 @@ class calendar extends rcube_plugin $title = $this->gettext('print'); $view = rcube_utils::get_input_value('view', rcube_utils::INPUT_GPC); - if (!in_array($view, array('agendaWeek', 'agendaDay', 'month', 'table'))) + if (!in_array($view, array('agendaWeek', 'agendaDay', 'month', 'list'))) $view = 'agendaDay'; $this->rc->output->set_env('view',$view); diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index 03d275ae..c54a6904 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -74,28 +74,28 @@ function rcube_calendar_ui(settings) // global fullcalendar settings var fullcalendar_defaults = { aspectRatio: 1, - ignoreTimezone: true, // will treat the given date strings as in local (browser's) timezone - monthNames : settings.months, - monthNamesShort : settings.months_short, - dayNames : settings.days, - dayNamesShort : settings.days_short, - firstDay : settings.first_day, - firstHour : settings.first_hour, - slotMinutes : 60/settings.timeslots, + timezone: false, // will treat the given date strings as in local (browser's) timezone + monthNames: settings.months, + monthNamesShort: settings.months_short, + dayNames: settings.days, + dayNamesShort: settings.days_short, + firstDay: settings.first_day, + firstHour: settings.first_hour, + slotDuration: {minutes: 60/settings.timeslots}, businessHours: { start: settings.work_start + ':00', end: settings.work_end + ':00' }, views: { -/* - basic: { - timeFormat: settings.time_format, + list: { + titleFormat: settings.dates_long, + visibleRange: function(currentDate) { + return { + start: currentDate.clone(), + end: currentDate.clone().add(settings.agenda_range, 'days') + } + } }, - year: { - columnFormat: settings.date_agenda, - titleFormat: settings.dates_long - }, -*/ month: { columnFormat: 'ddd', // Mon titleFormat: 'MMMM YYYY', @@ -112,12 +112,6 @@ function rcube_calendar_ui(settings) }, timeFormat: settings.time_format, axisFormat : settings.time_format, -/* - listPage: 7, // advance one week in agenda view - listRange: settings.agenda_range, - listSections: settings.agenda_sections, - tableCols: ['handle', 'date', 'time', 'title', 'location'], -*/ defaultView: rcmail.env.view || settings.default_view, allDayText: rcmail.gettext('all-day', 'calendar'), weekNumbers: settings.show_weekno > 0, @@ -127,16 +121,18 @@ function rcube_calendar_ui(settings) day: rcmail.gettext('day', 'calendar'), week: rcmail.gettext('week', 'calendar'), month: rcmail.gettext('month', 'calendar'), - listYear: rcmail.gettext('agenda', 'calendar') + list: rcmail.gettext('agenda', 'calendar') }, buttonIcons: { prev: 'left-single-arrow', next: 'right-single-arrow' }, theme: false, + nowIndicator: settings.time_indicator, eventLimitText: function(num) { return rcmail.gettext('andnmore', 'calendar').replace('$nr', num); }, + noEventsMessage: rcmail.gettext('calendar.searchnoresults'), /* listTexts: { until: rcmail.gettext('until', 'calendar'), @@ -151,10 +147,9 @@ function rcube_calendar_ui(settings) week: rcmail.gettext('weekofyear', 'calendar') }, */ - nowIndicator: settings.time_indicator, // event rendering eventRender: function(event, element, view) { - if (view.name != 'list' && view.name != 'table') { + if (view.name != 'list') { var prefix = event.sensitivity && event.sensitivity != 'public' ? String(sensitivitylabels[event.sensitivity]).toUpperCase()+': ' : ''; element.attr('title', prefix + event.title); } @@ -2674,8 +2669,8 @@ function rcube_calendar_ui(settings) var update_agenda_toolbar = function() { - $('#agenda-listrange').val(fc.fullCalendar('option', 'listRange')); - $('#agenda-listsections').val(fc.fullCalendar('option', 'listSections')); +// $('#agenda-listrange').val(); +// $('#agenda-listsections').val(fc.fullCalendar('option', 'listSections')); } @@ -2865,9 +2860,15 @@ function rcube_calendar_ui(settings) { if (!view) view = fc.fullCalendar('getView').name; var date = fc.fullCalendar('getDate').toDate(); - var range = fc.fullCalendar('option', 'listRange'); - var sections = fc.fullCalendar('option', 'listSections'); - rcmail.open_window(rcmail.url('print', { view: view, date: date2unixtime(date), range: range, sections: sections, search: this.search_query }), true, true); +// var sections = fc.fullCalendar('option', 'listSections'); + + rcmail.open_window(rcmail.url('print', { + view: view, + date: date2unixtime(date), + range: settings.agenda_range, + // sections: sections, + search: this.search_query + }), true, true); }; // public method to bring up the new event dialog @@ -3388,12 +3389,11 @@ function rcube_calendar_ui(settings) if (this._search_message) rcmail.hide_message(this._search_message); - for (var sid in this.calendars) { - if (this.calendars[sid]) { - this.calendars[sid].url = this.calendars[sid].url.replace(/&q=.+/, '') + '&q=' + urlencode(q); - sources.push(sid); - } - } + $.each(fc.fullCalendar('getEventSources'), function() { + this.url = this.url.replace(/&q=.+/, '') + '&q=' + urlencode(q); + me.calendars[this.id].url = this.url; + sources.push(this.id); + }); id += '@'+sources.join(','); // ignore if query didn't change @@ -3409,10 +3409,8 @@ function rcube_calendar_ui(settings) this.search_query = q; // change to list view - fc.fullCalendar('option', 'listSections', 'month'); - fc.fullCalendar('option', 'listRange', Math.max(60, settings.agenda_range)); - // TODO: fullcalendar 3.9 has dateOrRange argument here, shall we use it? - fc.fullCalendar('changeView', 'listYear'); + // fc.fullCalendar('option', 'listSections', 'month'); + fc.fullCalendar('changeView', 'list'); update_agenda_toolbar(); @@ -3434,90 +3432,30 @@ function rcube_calendar_ui(settings) rcmail.hide_message(this._search_message); if (this.search_request) { - // hide bottom links of agenda view - fc.find('.fc-list-content > .fc-listappend').hide(); - // restore original event sources and view mode from fullcalendar - fc.fullCalendar('option', 'listSections', settings.agenda_sections); - fc.fullCalendar('option', 'listRange', settings.agenda_range); - + // fc.fullCalendar('option', 'listSections', settings.agenda_sections); update_agenda_toolbar(); - for (var sid in this.calendars) { - if (this.calendars[sid]) - this.calendars[sid].url = this.calendars[sid].url.replace(/&q=.+/, ''); - } - if (this.default_view) - fc.fullCalendar('changeView', this.default_view); - - if (!this.is_loading) - fc.fullCalendar('refetchEvents'); + $.each(fc.fullCalendar('getEventSources'), function() { + this.url = this.url.replace(/&q=.+/, ''); + me.calendars[this.id].url = this.url; + }); + + fc.fullCalendar('refetchEvents'); this.search_request = this.search_query = null; } }; // callback if all sources have been fetched from server - this.events_loaded = function(count) + this.events_loaded = function() { var addlinks, append = ''; - + // enhance list view when searching if (this.search_request) { - if (!count) { + if (!fc.fullCalendar('clientEvents').length) { this._search_message = rcmail.display_message(rcmail.gettext('searchnoresults', 'calendar'), 'notice'); - append = '
' + rcmail.gettext('searchnoresults', 'calendar') + '
'; - } - append += ''; - addlinks = true; - } - - if (fc.fullCalendar('getView').name == 'table') { - var elastic = $('#calendar').data('elastic-mode'); - var container = elastic ? $('#searchcontrols') : fc.find('.fc-list-content > .fc-listappend'); - if (append) { - if (!container.length) - container = $('
').appendTo(fc.find('.fc-list-content')); - container.html(append).show(); - } - else if (container.length) - container.hide(); - - // add links to adjust search date range - if (addlinks) { - var lc = container.find('.fc-bottomlinks'); - - if (elastic) { - $('').attr({href: '#', 'class': 'button icon tools'}) - .append($('').text(rcmail.gettext('showtools'))) - .prependTo('#searchcontrols') - .click(function() { - $(this).attr('title', rcmail.gettext($('#searchcontrols').toggleClass('open').is('.open') ? 'hidetools' : 'showtools')); - }); - } - - $('').attr({href: '#', 'class': 'button prev'}) - .append($('').text(rcmail.gettext(elastic ? 'earlierevents' : 'searchearlierdates', 'calendar'))) - .appendTo(lc) - .click(function() { - fc.fullCalendar('incrementDate', "-P1M"); - }); - - lc.append(" "); - - $('').attr({href: '#', 'class': 'button next'}) - .append($('').text(rcmail.gettext(elastic ? 'laterevents' : 'searchlaterdates', 'calendar'))) - .appendTo(lc) - .click(function() { - var range = fc.fullCalendar('option', 'listRange'); - if (range < 90) { - fc.fullCalendar('option', 'listRange', fc.fullCalendar('option', 'listRange') + 30); - fc.fullCalendar('render'); - update_agenda_toolbar(); - } - else - fc.fullCalendar('incrementDate', "P1M"); - }); } } @@ -3528,7 +3466,7 @@ function rcube_calendar_ui(settings) // adjust calendar view size this.view_resize = function() { - var footer = fc.fullCalendar('getView').name == 'table' ? $('#agendaoptions').outerHeight() : 0; + var footer = fc.fullCalendar('getView').name == 'list' ? $('#agendaoptions').outerHeight() : 0; fc.fullCalendar('option', 'height', $('#calendar').height() - footer); }; @@ -3805,7 +3743,7 @@ function rcube_calendar_ui(settings) header: { right: 'prev,next today', center: 'title', - left: 'agendaDay,agendaWeek,month,listYear' + left: 'agendaDay,agendaWeek,month,list' }, date: viewdate.getDate(), month: viewdate.getMonth(), @@ -3817,9 +3755,9 @@ function rcube_calendar_ui(settings) loading: function(isLoading) { me.is_loading = isLoading; this._rc_loading = rcmail.set_busy(isLoading, 'loading', this._rc_loading); - // trigger callback + // trigger callback (using timeout, otherwise clientEvents is always empty) if (!isLoading) - me.events_loaded($(this).fullCalendar('clientEvents').length); + setTimeout(function() { me.events_loaded(); }, 20); }, // callback for date range selection select: function(start, end, e, view) { @@ -3892,8 +3830,8 @@ function rcube_calendar_ui(settings) update_event_confirm('resize', event, data); }, - viewRender: function(view) { - $('#agendaoptions')[view.name == 'listYear' ? 'show' : 'hide'](); + 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) @@ -3901,6 +3839,20 @@ function rcube_calendar_ui(settings) current_view = view.name; me.update_state(); } + + var prev = $('#calendar .fc-prev-button').off('click.list'), + next = $('#calendar .fc-next-button').off('click.list'); + + if (view.name == 'list') { + var viewStart = moment(view.start); + + prev.on('click.list', function() { + fc.fullCalendar('gotoDate', viewStart.subtract(settings.agenda_range, 'days')); + }); + next.on('click.list', function() { + fc.fullCalendar('gotoDate', viewStart.add(settings.agenda_range, 'days')); + }); + } } })); @@ -4193,18 +4145,17 @@ function rcube_calendar_ui(settings) $('#agenda-listrange').change(function(e){ settings.agenda_range = parseInt($(this).val()); - fc.fullCalendar('option', 'listRange', settings.agenda_range) - fc.fullCalendar('render'); + fc.fullCalendar('changeView', 'list'); // TODO: save new settings in prefs }).val(settings.agenda_range); - +/* $('#agenda-listsections').change(function(e){ settings.agenda_sections = $(this).val(); fc.fullCalendar('option', 'listSections', settings.agenda_sections); - fc.fullCalendar('render'); + fc.fullCalendar('changeView', 'list'); // TODO: save new settings in prefs }).val(fc.fullCalendar('option', 'listSections')); - +*/ // hide event dialog when clicking somewhere into document $(document).bind('mousedown', dialog_check); diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css index 3f700896..fedaaeca 100644 --- a/plugins/calendar/skins/larry/calendar.css +++ b/plugins/calendar/skins/larry/calendar.css @@ -1634,6 +1634,10 @@ a.dropdown-link:after { /* fullcalendar style overrides */ +.fc-scroller { + background: #fff; +} + .calendarmain .fc-body { background: #fff; } @@ -1691,7 +1695,7 @@ a.dropdown-link:after { color: #555; min-width: 50px; max-width: 75px; - height: 43px; + height: 40px; line-height: 1em; overflow: hidden; text-overflow: ellipsis; @@ -1702,13 +1706,7 @@ a.dropdown-link:after { border: 0; background: url(images/toolbar.png) center 100px no-repeat; box-shadow: none; - -o-box-shadow: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; outline: none; - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; transition: none; } @@ -1754,12 +1752,11 @@ a.dropdown-link:after { background-position: center -320px; } -.calendarmain #calendar .fc-left .fc-listYear-button { +.calendarmain #calendar .fc-left .fc-list-button { background-position: center -360px; - display: none; /* hide Agenda button for now */ } -.calendarmain #calendar .fc-left .fc-listYear.fc-state-active { +.calendarmain #calendar .fc-left .fc-list-button.fc-state-active { background-position: center -400px; } @@ -1783,7 +1780,7 @@ a.dropdown-link:after { } #calendar .fc-toolbar.fc-header-toolbar { - margin-bottom: 4px; + margin-bottom: 7px; margin-right: 250px; } @@ -1853,21 +1850,25 @@ a.dropdown-link:after { opacity: .25; } -.fc-view-table tr.fc-invitation-tentative td, -.fc-view-table tr.fc-invitation-declined td, -.fc-view-table tr.fc-invitation-needs-action td { +.fc-list-view { + border-bottom: 0; +} + +.fc-list-table tr.fc-invitation-tentative td, +.fc-list-table tr.fc-invitation-declined td, +.fc-list-table tr.fc-invitation-needs-action td { color: #888; } -.fc-view-table tr.fc-invitation-tentative td.fc-title, -.fc-view-table tr.fc-invitation-declined td.fc-title, -.fc-view-table tr.fc-invitation-needs-action td.fc-title { +.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 { font-weight: normal; } -#quickview-calendar .fc-view-table tr.fc-invitation-tentative td, -#quickview-calendar .fc-view-table tr.fc-invitation-declined td, -#quickview-calendar .fc-view-table tr.fc-invitation-needs-action td { +#quickview-calendar .fc-list-table tr.fc-invitation-tentative td, +#quickview-calendar .fc-list-table tr.fc-invitation-declined td, +#quickview-calendar .fc-list-table tr.fc-invitation-needs-action td { color: #333; } @@ -1984,12 +1985,21 @@ a.dropdown-link:after { cursor: pointer; } -.calendarmain .fc-view-table td.fc-list-header { +.fc-list-table td.fc-list-header { color: #004458; font-size: 12px; } -.calendarmain .fc-view-table tr.fc-event td { +.fc-list-table tr.fc-list-item { + background: transparent; +} + +.fc-list-table tr.fc-list-item:hover td { + background: transparent; + cursor: pointer; +} + +.fc-list-table tr.fc-list-item td { border-color: #bbd3da; padding: 6px 8px; white-space: nowrap; @@ -1997,12 +2007,12 @@ a.dropdown-link:after { text-overflow: ellipsis; } -.calendarmain .fc-view-table tr.fc-event td.fc-event-handle { +.fc-list-table tr.fc-list-item td.fc-event-handle { padding: 6px 0 2px 7px; width: 12px; } -.calendarmain .fc-view-table .fc-event-handle .fc-event-skin { +.fc-list-table .fc-event-handle .fc-event-skin { margin: 0; padding: 0; display: inline-block; @@ -2012,7 +2022,7 @@ a.dropdown-link:after { border-radius: 8px; } -.calendarmain .fc-view-table .fc-event-handle .fc-event-inner { +.fc-list-table .fc-event-handle .fc-event-inner { display: inline-block; width: 10px; height: 10px; @@ -2023,26 +2033,14 @@ a.dropdown-link:after { border: 1px solid rgba(0, 0, 0, 0.4); } -.calendarmain .fc-view-table col.fc-event-location { +.calendarmain .fc-list-table col.fc-event-location { width: 25%; } -.fc-listappend { - text-align: center; - margin: 1em 0; -} - -.fc-listappend .message { - padding: 0.5em; - margin-bottom: 0.5em; +.fc-list-empty { font-size: 150%; color: #999; -} - -.fc-listappend .formlinks a { - font-size: 12px; - padding: 0 0.3em; - max-width: initial; + background: unset !important; } .fc-event-temp { @@ -2055,7 +2053,7 @@ a.dropdown-link:after { } .fc-time-grid .fc-now-indicator { - border-top: 2px solid #3ec400; + border: 1px solid #3ec400; } /* Settings section */ diff --git a/plugins/libcalendaring/libcalendaring.php b/plugins/libcalendaring/libcalendaring.php index d79a0b8e..5f5d12eb 100644 --- a/plugins/libcalendaring/libcalendaring.php +++ b/plugins/libcalendaring/libcalendaring.php @@ -1477,8 +1477,8 @@ class libcalendaring extends rcube_plugin 'M' => 'n', 'dddd' => 'l', 'ddd' => 'D', - 'dd' => 'd', - 'd' => 'j', + 'DD' => 'd', + 'D' => 'j', 'HH' => '**', 'hh' => '%%', 'H' => 'G', @@ -1511,8 +1511,8 @@ class libcalendaring extends rcube_plugin 'n' => 'M', 'j' => 'D', 'd' => 'DD', - 'D' => 'DDD', - 'l' => 'DDDD', + 'D' => 'ddd', + 'l' => 'dddd', 'H' => 'HH', 'h' => 'hh', 'G' => 'H',