plugins/calendar plugins/libcalendaring

Thomas Brüderli bruederli at kolabsys.com
Wed Sep 10 10:31:05 CEST 2014


 plugins/calendar/calendar.php                          |   46 ++++++++++++++-
 plugins/calendar/calendar_ui.js                        |   51 ++++++++++++++++-
 plugins/calendar/localization/en_US.inc                |    1 
 plugins/calendar/skins/classic/templates/calendar.html |    2 
 plugins/calendar/skins/larry/calendar.css              |    8 ++
 plugins/calendar/skins/larry/templates/calendar.html   |    2 
 plugins/libcalendaring/lib/libcalendaring_itip.php     |   14 ++++
 plugins/libcalendaring/libcalendaring.js               |   12 ++++
 plugins/libcalendaring/localization/en_US.inc          |    1 
 9 files changed, 128 insertions(+), 9 deletions(-)

New commits:
commit 09cf967ed5799a3e8701f906123df2b9746e70c2
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Wed Sep 10 10:30:40 2014 +0200

    Add button to iTip RSVP UI in mail view to open the calendar preview with an option to accept/decline the invitation from there (#3161)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index afcc052..9c0a892 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -309,10 +309,13 @@ class calendar extends rcube_plugin
     $view = get_input_value('view', RCUBE_INPUT_GPC);
     if (in_array($view, array('agendaWeek', 'agendaDay', 'month', 'table')))
       $this->rc->output->set_env('view', $view);
-    
+
     if ($date = get_input_value('date', RCUBE_INPUT_GPC))
       $this->rc->output->set_env('date', $date);
 
+    if ($msgref = get_input_value('itip', RCUBE_INPUT_GPC))
+      $this->rc->output->set_env('itip_events', $this->itip_events($msgref));
+
     $this->rc->output->send("calendar.calendar");
   }
 
@@ -1123,6 +1126,43 @@ class calendar extends rcube_plugin
   }
 
   /**
+   * Load event data from an iTip message attachment
+   */
+  public function itip_events($msgref)
+  {
+    $path = explode('/', $msgref);
+    $msg = array_pop($path);
+    $mbox = join('/', $path);
+    list($uid, $mime_id) = explode('#', $msg);
+    $events = array();
+
+    if ($event = $this->lib->mail_get_itip_object($mbox, $uid, $mime_id, 'event')) {
+      $partstat = 'NEEDS-ACTION';
+/*
+      $user_emails = $this->lib->get_user_emails();
+      foreach ($event['attendees'] as $attendee) {
+        if (in_array($attendee['email'], $user_emails)) {
+          $partstat = $attendee['status'];
+          break;
+        }
+      }
+*/
+      $event['id'] = $event['uid'];
+      $event['temporary'] = true;
+      $event['readonly'] = true;
+      $event['calendar'] = '--invitation--itip';
+      $event['className'] = 'fc-invitation-' . strtolower($partstat);
+      $event['_mbox'] = $mbox;
+      $event['_uid']  = $uid;
+      $event['_part'] = $mime_id;
+
+      $events[] = $this->_client_event($event, true);
+    }
+
+    return $events;
+  }
+
+  /**
    * Handler for keep-alive requests
    * This will check for updated data in active calendars and sync them to the client
    */
@@ -2357,7 +2397,8 @@ class calendar extends rcube_plugin
             $ical_objects->method,
             $ical_objects->mime_id . ':' . $idx,
             'calendar',
-            rcube_utils::anytodatetime($ical_objects->message_date)
+            rcube_utils::anytodatetime($ical_objects->message_date),
+            $this->rc->url(array('task' => 'calendar')) . '&view=agendaDay&date=' . $event['start']->format('U')
           )
         );
       }
@@ -2566,6 +2607,7 @@ class calendar extends rcube_plugin
     }
 
     if ($success || $dontsave) {
+      $metadata['calendar'] = $event['calendar'];
       $metadata['nosave'] = $dontsave;
       $metadata['rsvp'] = intval($metadata['rsvp']);
       $metadata['after_action'] = $this->rc->config->get('calendar_itip_after_action', $this->defaults['calendar_itip_after_action']);
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 558a014..ef40938 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -599,7 +599,7 @@ function rcube_calendar_ui(settings)
       me.dialog_resize($dialog.get(0), $dialog.height(), 420);
 
       // add link for "more options" drop-down
-      if (!temp) {
+      if (!temp && !event.temporary) {
         $('<a>')
           .attr('href', '#')
           .html(rcmail.gettext('eventoptions','calendar'))
@@ -2339,7 +2339,19 @@ function rcube_calendar_ui(settings)
         var submit_data = $.extend({}, me.selected_event, { source:null, comment:$('#reply-comment-event-rsvp').val() }),
           noreply = $('#noreply-event-rsvp:checked').length ? 1 : 0;
 
-        if (settings.invitation_calendars) {
+        // import event from mail (temporary iTip event)
+        if (submit_data._mbox && submit_data._uid) {
+          me.saving_lock = rcmail.set_busy(true, 'calendar.savingdata');
+          rcmail.http_post('mailimportitip', {
+            _mbox: submit_data._mbox,
+            _uid:  submit_data._uid,
+            _part: submit_data._part,
+            _status:  response,
+            _noreply: noreply,
+            _comment: submit_data.comment
+          });
+        }
+        else if (settings.invitation_calendars) {
           update_event('rsvp', submit_data, { status:response, noreply:noreply });
         }
         else {
@@ -3089,6 +3101,25 @@ function rcube_calendar_ui(settings)
       return query;
     };
 
+    // callback after an iTip message event was imported
+    this.itip_message_processed = function(data)
+    {
+      // remove temporary iTip source
+      fc.fullCalendar('removeEventSource', this.calendars['--invitation--itip']);
+
+      $('#eventshow:ui-dialog').dialog('close');
+      this.selected_event = null;
+
+      // refresh destination calendar source
+      this.refresh({ source:data.calendar, refetch:true });
+
+      this.unlock_saving();
+
+      // process 'after_action' in mail task
+      if (window.opener && window.opener.rcube_libcalendaring)
+        window.opener.rcube_libcalendaring.itip_message_processed(data);
+    };
+
     // reload the calendar view by keeping the current date/view selection
     this.reload_view = function()
     {
@@ -3462,7 +3493,20 @@ function rcube_calendar_ui(settings)
     var viewdate = new Date();
     if (rcmail.env.date)
       viewdate.setTime(fromunixtime(rcmail.env.date));
-    
+
+    // add source with iTip event data for rendering
+    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,
+        attendees: true
+      };
+      event_sources.push(me.calendars['--invitation--itip']);
+    }
+
     // initalize the fullCalendar plugin
     var fc = $('#calendar').fullCalendar($.extend({}, fullcalendar_defaults, {
       header: {
@@ -3940,6 +3984,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
   rcmail.addEventListener('plugin.render_event_changelog', function(data){ cal.render_event_changelog(data); });
   rcmail.addEventListener('plugin.event_show_diff', function(data){ cal.event_show_diff(data); });
   rcmail.addEventListener('plugin.event_show_revision', function(data){ cal.event_show_dialog(data, null, true); });
+  rcmail.addEventListener('plugin.itip_message_processed', function(data){ cal.itip_message_processed(data); });
   rcmail.addEventListener('requestrefresh', function(q){ return cal.before_refresh(q); });
 
   // let's go
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index e52f62a..6023366 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -201,6 +201,7 @@ $labels['eventcancelled'] = 'The event has been cancelled';
 $labels['saveincalendar'] = 'save in';
 $labels['updatemycopy'] = 'Update in my calendar';
 $labels['savetocalendar'] = 'Save to calendar';
+$labels['openpreview'] = 'Check Calendar';
 
 // resources
 $labels['resource'] = 'Resource';
diff --git a/plugins/calendar/skins/classic/templates/calendar.html b/plugins/calendar/skins/classic/templates/calendar.html
index 516cf58..5f006d2 100644
--- a/plugins/calendar/skins/classic/templates/calendar.html
+++ b/plugins/calendar/skins/classic/templates/calendar.html
@@ -6,7 +6,7 @@
 <script type="text/javascript" src="/functions.js"></script>
 <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="./plugins/calendar/skins/classic/iehacks.css" /><![endif]-->
 </head>
-<body class="calendarmain">
+<roundcube:if condition="env:extwin" /><body class="calendarmain extwin"><roundcube:else /><body class="calendarmain"><roundcube:endif />
 
 <roundcube:include file="/includes/taskbar.html" />
 <roundcube:include file="/includes/header.html" />
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index ca439ff..5e8c09d 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -1,7 +1,7 @@
 /**
  * Roundcube Calendar plugin styles for skin "Larry"
  *
- * Copyright (c) 2012, Kolab Systems AG <contact at kolabsys.com>
+ * Copyright (c) 2012-2014, Kolab Systems AG <contact at kolabsys.com>
  * Screendesign by FLINT / Büro für Gestaltung, bueroflint.com
  *
  * The contents are subject to the Creative Commons Attribution-ShareAlike
@@ -2016,9 +2016,15 @@ div.calendar-invitebox input.button {
 	margin-right: 0.5em;
 }
 
+div.calendar-invitebox input.button.preview {
+	margin-left: 1em;
+	margin-right: 0;
+}
+
 div.calendar-invitebox .folder-select {
 	font-weight: 10px;
 	margin-left: 1em;
+	white-space: nowrap;
 }
 
 div.calendar-invitebox .rsvp-status {
diff --git a/plugins/calendar/skins/larry/templates/calendar.html b/plugins/calendar/skins/larry/templates/calendar.html
index c607c87..1df1748 100644
--- a/plugins/calendar/skins/larry/templates/calendar.html
+++ b/plugins/calendar/skins/larry/templates/calendar.html
@@ -5,7 +5,7 @@
 <roundcube:include file="/includes/links.html" />
 <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/this/iehacks.css" /><![endif]-->
 </head>
-<body class="calendarmain">
+<roundcube:if condition="env:extwin" /><body class="calendarmain extwin"><roundcube:else /><body class="calendarmain"><roundcube:endif />
 
 <roundcube:include file="/includes/header.html" />
 
diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php
index ce68655..a5b056f 100644
--- a/plugins/libcalendaring/lib/libcalendaring_itip.php
+++ b/plugins/libcalendaring/lib/libcalendaring_itip.php
@@ -361,6 +361,7 @@ class libcalendaring_itip
       return array(
           'uid' => $event['uid'],
           'id' => asciiwords($event['uid'], true),
+          'existing' => $existing ? true : false,
           'saved' => $existing ? true : false,
           'latest' => $latest,
           'status' => $status,
@@ -372,7 +373,7 @@ class libcalendaring_itip
     /**
      * Build inline UI elements for iTip messages
      */
-    public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null)
+    public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null, $preview_url = null)
     {
         $buttons = array();
         $dom_id = asciiwords($event['uid'], true);
@@ -450,6 +451,17 @@ class libcalendaring_itip
                 ));
             }
 
+            // add button to open calendar/preview
+            if (!empty($preview_url)) {
+              $msgref = $this->lib->ical_message->folder . '/' . $this->lib->ical_message->uid . '#' . $mime_id;
+              $rsvp_buttons .= html::tag('input', array(
+                  'type' => 'button',
+                  'class' => "button preview",
+                  'onclick' => "rcube_libcalendaring.open_itip_preview('" . JQ($preview_url) . "', '" . JQ($msgref) . "')",
+                  'value' => $this->gettext('openpreview'),
+              ));
+            }
+
             // 2. update the local copy with minor changes
             $update_button = html::tag('input', array(
                 'type' => 'button',
diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index cd06827..b23a3fe 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -892,6 +892,7 @@ rcube_libcalendaring.fetch_itip_object_status = function(p)
 rcube_libcalendaring.update_itip_object_status = function(p)
 {
   rcmail.env.rsvp_saved = p.saved;
+  rcmail.env.itip_existing = p.existing;
 
   // hide all elements first
   $('#itip-buttons-'+p.id+' > div').hide();
@@ -953,6 +954,17 @@ rcube_libcalendaring.itip_after_action = function(action)
   }
 };
 
+/**
+ * Open the calendar preview for the current iTip event
+ */
+rcube_libcalendaring.open_itip_preview = function(url, msgref)
+{
+  if (!rcmail.env.itip_existing)
+    url += '&itip=' + escape(msgref);
+
+  var win = rcmail.open_window(url);
+};
+
 
 // extend jQuery
 (function($){
diff --git a/plugins/libcalendaring/localization/en_US.inc b/plugins/libcalendaring/localization/en_US.inc
index 82fb7a8..9c3507c 100644
--- a/plugins/libcalendaring/localization/en_US.inc
+++ b/plugins/libcalendaring/localization/en_US.inc
@@ -134,6 +134,7 @@ $labels['outdatedinvitation'] = 'This invitation has been replaced by a newer ve
 $labels['importtocalendar'] = 'Save to my calendar';
 $labels['removefromcalendar'] = 'Remove from my calendar';
 $labels['updatemycopy'] = 'Update my copy';
+$labels['openpreview'] = 'Open Preview';
 
 $labels['deleteobjectconfirm'] = 'Do you really want to delete this object?';
 $labels['declinedeleteconfirm'] = 'Do you also want to delete this declined object from your account?';




More information about the commits mailing list