From 008c5db5d950f6dfee3458a20264f68a26e5cf6e Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Tue, 13 May 2014 17:09:53 +0200 Subject: [PATCH] Implement searching for unsubscribed IMAP folders and temporary/session subscriptions --- plugins/calendar/calendar.php | 22 ++- plugins/calendar/calendar_ui.js | 141 ++++++++++++++++-- plugins/calendar/drivers/calendar_driver.php | 9 ++ .../drivers/database/database_driver.php | 13 ++ .../calendar/drivers/kolab/kolab_calendar.php | 7 +- .../calendar/drivers/kolab/kolab_driver.php | 121 ++++++++++++--- plugins/calendar/lib/calendar_ui.php | 58 ++++--- plugins/calendar/localization/en_US.inc | 1 + plugins/calendar/skins/larry/calendar.css | 67 +++++---- .../kolab_addressbook/kolab_addressbook.php | 2 +- plugins/libkolab/lib/kolab_storage.php | 78 ++++++++-- 11 files changed, 411 insertions(+), 108 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 1d40efe5..fc0069d4 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -725,9 +725,29 @@ class calendar extends rcube_plugin $this->rc->output->command('plugin.destroy_source', array('id' => $cal['id'])); break; case "subscribe": - if (!$this->driver->subscribe_calendar($cal)) + if (!$this->driver->subscribe_calendar($cal, intval(get_input_value('perm', RCUBE_INPUT_GPC)))) $this->rc->output->show_message($this->gettext('errorsaving'), 'error'); return; + case "search": + $results = array(); + $color_mode = $this->rc->config->get('calendar_event_coloring', $this->defaults['calendar_event_coloring']); + foreach ((array)$this->driver->search_calendars(get_input_value('q', RCUBE_INPUT_GPC), get_input_value('source', RCUBE_INPUT_GPC)) as $id => $prop) { + $editname = $prop['editname']; + unset($prop['editname']); // force full name to be displayed + $prop['active'] = false; + + // let the UI generate HTML and CSS representation for this calendar + $html = $this->ui->calendar_list_item($id, $prop, $jsenv); + $cal = $jsenv[$id]; + $cal['editname'] = $editname; + $cal['html'] = $html; + if (!empty($prop['color'])) + $cal['css'] = $this->ui->calendar_css_classes($id, $prop, $color_mode); + + $results[] = $cal; + } + $this->rc->output->command('multi_thread_http_response', $results, get_input_value('_reqid', RCUBE_INPUT_GPC)); + return; } if ($success) diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index 2a8a8d2b..4db85937 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -39,6 +39,7 @@ function rcube_calendar_ui(settings) this.selected_calendar = null; this.search_request = null; this.saving_lock; + this.calendars = {}; /*** private vars ***/ @@ -52,6 +53,9 @@ function rcube_calendar_ui(settings) var event_defaults = { free_busy:'busy', alarms:'' }; var event_attendees = []; var calendars_list; + var calenders_search_list; + var calenders_search_container; + var search_calendars = {}; var attendees_list; var resources_list; var resources_treelist; @@ -2667,16 +2671,79 @@ function rcube_calendar_ui(settings) this.selected_calendar = id; }; + // render the results for calendar list search + var calendar_search_results = function(results) + { + if (results.length) { + // create treelist widget to present the search results + if (!calenders_search_list) { + calenders_search_container = $('
') + .html('

' + rcmail.gettext('calsearchresults','calendar') + '

') + .insertAfter(rcmail.gui_objects.calendarslist); - /*** startup code ***/ + calenders_search_list = new rcube_treelist_widget('', { + id_prefix: 'rcmlical', + selectable: false + }); - // create list of event sources AKA calendars - this.calendars = {}; - var id, li, cal, active, color, brightness, event_sources = []; - for (id in rcmail.env.calendars) { - cal = rcmail.env.calendars[id]; - this.calendars[id] = $.extend({ - url: "./?_task=calendar&_action=load_events&source="+escape(id), + // register click handler on search result's checkboxes to select the given calendar for listing + calenders_search_list.container + .appendTo(calenders_search_container) + .on('click', 'input[type=checkbox]', function(e){ + var li = $(this).closest('li'), + id = li.attr('id').replace(/^rcmlical/, ''), + prop = search_calendars[id], + parent_id = prop.parent || null; + + if (!this.checked) + return; + + // find parent node and insert at the right place + if (parent_id && $('#rcmlical'+parent_id, rcmail.gui_objects.calendarslist).length) { + prop.listname = prop.editname; + li.children().first().find('.calname').html(Q(prop.listname)); + } + + // move this calendar to the calendars_list widget + calendars_list.insert({ + id: id, + classes: [], + html: li.children().first() + }, parent_id, parent_id ? true : false); + + search_calendars[id].active = true; + add_calendar_source(prop); + li.remove(); + + // add css classes related to this calendar to document + if (cal.css) { + $('') + .html(cal.css) + .appendTo('head'); + } + }); + } + + for (var cal, i=0; i < results.length; i++) { + cal = results[i]; + search_calendars[cal.id] = cal; + $('
  • ') + .attr('id', 'rcmlical' + cal.id) + .html(cal.html) + .appendTo(calenders_search_list.container); + } + + calenders_search_container.show(); + } + }; + + // register the given calendar to the current view + var add_calendar_source = function(cal) + { + var color, brightness, select, id = cal.id; + + me.calendars[id] = $.extend({ + url: rcmail.url('calendar/load_events', { source: id }), editable: !cal.readonly, className: 'fc-event-cal-'+id, id: id @@ -2689,18 +2756,40 @@ function rcube_calendar_ui(settings) // 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) - this.calendars[id].textColor = 'black'; + me.calendars[id].textColor = 'black'; } + + me.calendars[id].color = color; } - this.calendars[id].color = color; - - if ((active = cal.active || false)) { - event_sources.push(this.calendars[id]); + if (fc && cal.active) { + fc.fullCalendar('addEventSource', me.calendars[id]); + rcmail.http_post('calendar', { action:'subscribe', c:{ id:id, active:cal.active?1:0 } }); } + // insert to #calendar-select options if writeable + select = $('#edit-calendar'); + if (fc && !cal.readonly && select.length && !select.find('option[value="'+id+'"]').length) { + $('