0008722: Link to event in event notifications
authorCornelius Weiß <c.weiss@metaways.de>
Wed, 28 Jun 2017 13:16:49 +0000 (15:16 +0200)
committersstamer <s.stamer@metaways.de>
Fri, 30 Jun 2017 12:53:42 +0000 (14:53 +0200)
Change-Id: I03f9346c25ad8932fdb1a64a8c4cbd32b1fbf4a0
Reviewed-on: http://gerrit.tine20.com/customers/4972
Reviewed-by: sstamer <s.stamer@metaways.de>
Tested-by: sstamer <s.stamer@metaways.de>
tests/tine20/Calendar/Controller/EventTests.php
tine20/Calendar/Controller/Event.php
tine20/Calendar/Controller/EventNotifications.php
tine20/Calendar/Model/Event.php
tine20/Calendar/Model/Rrule.php
tine20/Calendar/js/Calendar.js
tine20/Calendar/js/DaysView.js
tine20/Calendar/js/MainScreenCenterPanel.js
tine20/Calendar/js/PagingToolbar.js
tine20/Calendar/views/eventNotification.php
tine20/Tinebase/js/data/RecordProxy.js

index 2eb5f51..df945f1 100644 (file)
@@ -76,7 +76,33 @@ class Calendar_Controller_EventTests extends Calendar_TestCase
         $this->assertTrue((bool) $loadedEvent->{Tinebase_Model_Grants::GRANT_EDIT});
         $this->assertTrue((bool) $loadedEvent->{Tinebase_Model_Grants::GRANT_DELETE});
     }
-    
+
+    public function testGetRecurInstance()
+    {
+        // create event and invite admin group
+        $event = $this->_getEvent();
+        $event->rrule = 'FREQ=DAILY;INTERVAL=1';
+
+        $persistentEvent = $this->_controller->create($event);
+        $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
+        $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($persistentEvent, $exceptions, Tinebase_DateTime::now());
+
+        $deepLink = $nextOccurance->getDeepLink();
+        $id = basename($deepLink);
+
+        $recurInstance = $this->_controller->get($id);
+        $this->assertTrue($recurInstance->isRecurInstance());
+        $this->assertEquals($nextOccurance->getId(), $recurInstance->getId());
+
+        // create recur exception in the meantime
+        $nextOccurance->summary = 'exception';
+        $this->_controller->createRecurException($nextOccurance);
+        $recurInstance = $this->_controller->get($id);
+//        print_r($recurInstance->toArray());
+        $this->assertFalse($recurInstance->isRecurInstance());
+        $this->assertEquals($nextOccurance->summary, $recurInstance->summary);
+    }
+
     /**
      * testUpdateEvent
      */
index 10e1cb8..22f1436 100644 (file)
@@ -1637,9 +1637,16 @@ class Calendar_Controller_Event extends Tinebase_Controller_Record_Abstract impl
      */
     public function get($_id, $_containerId = NULL, $_getRelatedData = TRUE, $_getDeleted = FALSE)
     {
-        if (preg_match('/^fakeid/', $_id)) {
-            // get base event when trying to fetch a non-persistent recur instance
-            return $this->getRecurBaseEvent(new Calendar_Model_Event(array('uid' => substr(str_replace('fakeid', '', $_id), 0, 40))), TRUE);
+        if (preg_match('/^fakeid(.*):(.*)/', $_id, $matches)) {
+            $baseEvent = $this->get($matches[1]);
+            $exceptions = $this->getRecurExceptions($baseEvent);
+            $originalDtStart = new Tinebase_DateTime($matches[2]);
+
+            $exdates = $exceptions->getOriginalDtStart();
+            $exdate = array_search($originalDtStart, $exdates);
+
+            return $exdate !== false ? $exceptions[$exdate] :
+                Calendar_Model_Rrule::computeNextOccurrence($baseEvent, $exceptions, $originalDtStart);
         } else {
             return parent::get($_id, $_containerId, $_getRelatedData, $_getDeleted);
         }
index f3e452b..f82447e 100644 (file)
             $view->event        = $_event;
             $view->updater      = $_updater;
             $view->updates      = $_updates;
+
+            $view->attendeeAccountId = $attendeeAccountId;
             
             $messageBody = $view->render('eventNotification.php');
             
index f1fe50d..ff875fb 100644 (file)
@@ -478,7 +478,17 @@ class Calendar_Model_Event extends Tinebase_Record_Abstract
     {
         return (boolean) preg_match('/^fakeid/', $this->getId());
     }
-    
+
+    /**
+     * returns a URL with a deep link path to the node provided
+     *
+     * @return string
+     */
+    public function getDeepLink()
+    {
+        return Tinebase_Core::getUrl() . '#/Calendar/showEvent/' . $this->getId();
+    }
+
     /**
      * sets recurId of this model
      * 
index a53ba59..1939211 100644 (file)
@@ -526,7 +526,7 @@ class Calendar_Model_Rrule extends Tinebase_Record_Abstract
      */
     protected static function addRecurrence($_recurrence, $_eventSet)
     {
-        $_recurrence->setId('fakeid' . $_recurrence->uid . $_recurrence->dtstart->getTimeStamp());
+        $_recurrence->setId('fakeid' . $_recurrence->base_event_id . ':' . $_recurrence->dtstart->getTimeStamp());
         
         // adjust alarms
         if ($_recurrence->alarms instanceof Tinebase_Record_RecordSet) {
index c25b95e..304294d 100644 (file)
@@ -81,6 +81,61 @@ Tine.Calendar.Application = Ext.extend(Tine.Tinebase.Application, {
         var imageUrl = Tine.Tinebase.common.getUrl('full') + '/images/view-calendar-day-' + new Date().getDate() + '.png';
         Ext.util.CSS.updateRule('.CalendarIconCls', 'background-image', 'url(' + imageUrl + ')');
 
+    },
+
+    routes: {
+        'showEvent/(.*)': 'showEvent'
+    },
+
+    /**
+     * display event in mainscreen
+     * @param {String} id
+     *
+     * example:
+     * http://tine20.example.com:10443/#/Calendar/showEvent/89192f9d3ce44ed3681a1b73d5ca491e766c4d62
+     */
+    showEvent: function(id) {
+        var cp = this.getMainScreen().getCenterPanel(),
+            activePanel = cp.getCalendarPanel(cp.activeView),
+            activeView = activePanel.getView(),
+            store = activeView.store;
+
+        cp.initialLoadAfterRender = false;
+
+        Tine.Tinebase.MainScreenPanel.show(this);
+
+        if (cp.loadMask) {
+            cp.loadMask.show();
+        }
+
+        Tine.Calendar.backend.loadRecord(id, {
+            success: function(record) {
+                // @TODO timeline view
+                store.on('load', function() {
+                    // NOTE: the store somehow changes, so refetch it
+                    var activePanel = cp.getCalendarPanel(cp.activeView),
+                        activeView = activePanel.getView(),
+                        sm = activeView.getSelectionModel(),
+                        store = activeView.store,
+                        event = store.getById(record.get('id'))
+
+                    if (! event) {
+                        store.add([record]);
+                        event = record;
+                    }
+
+                    sm.select.defer(250, sm, [event]);
+
+                }, this, { single: true });
+
+                activeView.updatePeriod({from: record.get('dtstart')});
+                cp.selectFavorite();
+            },
+            failure: function() {
+                cp.selectFavorite();
+                Ext.Msg.alert(this.i18n._('Event not found'), this.i18n._("The Event was deleted in the meantime or you don't have access rights to it."));
+            }
+        });
     }
 });
 
index ed9224d..3ade9d5 100644 (file)
@@ -1320,13 +1320,12 @@ Ext.extend(Tine.Calendar.DaysView, Tine.Calendar.AbstractView, {
      * updates HTML of day headers
      */
     updateDayHeaders: function() {
-        if (! this.rendered) {
-            return;
-        }
+        if (! this.rendered) return;
+
         var dayHeaders = Ext.DomQuery.select('div[class=cal-daysviewpanel-dayheader-day]', this.innerHd),
-            dayWidth = Ext.get(dayHeaders[0]).getWidth(),
+            dayWidth = dayHeaders ? Ext.get(dayHeaders[0]).getWidth() : [],
             headerString;
-            
+
         for (var i=0, date, isToDay, headerEl, dayColEl; i<dayHeaders.length; i++) {
             
             date = this.startDate.add(Date.DAY, i);
index 8c9fa80..cb226bf 100644 (file)
@@ -33,7 +33,12 @@ Tine.Calendar.MainScreenCenterPanel = Ext.extend(Ext.Panel, {
      * @cfg {Number} autoRefreshInterval (seconds)
      */
     autoRefreshInterval: 300,
-    
+
+    /**
+     * @cfg {Boolean} initialLoadAfterRender
+     */
+    initialLoadAfterRender: true,
+
     /**
      * @property autoRefreshTask
      * @type Ext.util.DelayedTask
@@ -501,18 +506,27 @@ Tine.Calendar.MainScreenCenterPanel = Ext.extend(Ext.Panel, {
      */
     onRender: function(ct, position) {
         Tine.Calendar.MainScreenCenterPanel.superclass.onRender.apply(this, arguments);
-        
-        var defaultFavorite = Tine.widgets.persistentfilter.model.PersistentFilter.getDefaultFavorite(this.app.appName, this.recordClass.prototype.modelName),
-            favoritesPanel  = this.app.getMainScreen().getWestPanel().getFavoritesPanel();
-        
+
         this.loadMask = new Ext.LoadMask(this.body, {msg: this.loadMaskText});
-        
-        if (defaultFavorite) {
-            favoritesPanel.selectFilter(defaultFavorite);
-        } else {
-            this.refresh();
+
+        var defaultFavorite = Tine.widgets.persistentfilter.model.PersistentFilter.getDefaultFavorite(this.app.appName, this.recordClass.prototype.modelName);
+
+        if (this.initialLoadAfterRender) {
+            if (defaultFavorite) {
+                this.selectFavorite(defaultFavorite);
+            } else {
+                this.refresh();
+            }
         }
     },
+
+    selectFavorite: function(favorite) {
+        var favorite = favorite || Tine.widgets.persistentfilter.model.PersistentFilter.getDefaultFavorite(this.app.appName, this.recordClass.prototype.modelName),
+            favoritesPanel  = this.app.getMainScreen().getWestPanel().getFavoritesPanel();
+
+        favoritesPanel.selectFilter(favorite);
+    },
+
     
     getViewParts: function (view) {
         view = String(view);
index 3d6107a..3f0cf13 100644 (file)
@@ -264,7 +264,7 @@ Tine.Calendar.PagingToolbar.DayPeriodPicker = Ext.extend(Tine.Calendar.PagingToo
         });
     },
     update: function(dtStart) {
-        this.dtStart = dtStart.clone();
+        this.dtStart = dtStart.clearTime(true);
         if (this.button && this.button.rendered) {
             this.button.setText(dtStart.format(Ext.DatePicker.prototype.format));
         }
@@ -369,7 +369,7 @@ Tine.Calendar.PagingToolbar.WeekPeriodPicker = Ext.extend(Tine.Calendar.PagingTo
     },
     update: function(dtStart) {
         //recalculate dtstart begin of week 
-        var from = dtStart.add(Date.DAY, -1 * dtStart.getDay());
+        var from = dtStart.clearTime(true).add(Date.DAY, -1 * dtStart.getDay());
         if (Ext.DatePicker.prototype.startDay) {
             from = from.add(Date.DAY, Ext.DatePicker.prototype.startDay - (dtStart.getDay() == 0 ? 7 : 0));
         }
@@ -518,7 +518,7 @@ Tine.Calendar.PagingToolbar.YearPeriodPicker = Ext.extend(Tine.Calendar.PagingTo
         
     },
     update: function(dtStart) {
-        this.dtStart = dtStart.clone();
+        this.dtStart = dtStart.clearTime(true);
         if (this.field && this.field.rendered) {
             this.field.setValue(dtStart.format('Y'));
         }
index a3ba658..e89e32d 100644 (file)
@@ -65,8 +65,14 @@ if ((isset($this->updates['attendee']) || array_key_exists('attendee', $this->up
 ?>
 
 <?php endif;?>
+<?php if ($this->attendeeAccountId): ?>
+
+<?php echo $this->translate->_('Link') ?>: <?php echo $this->event->getDeepLink();?>
+
+
+<?php endif;?>
 <?php echo $this->translate->_('Event details') ?>:
-<?php 
+<?php
 $orderedFields = array('dtstart', 'dtend', 'summary', 'location', 'description', 'rrule');
 
 foreach($orderedFields as $field) {
index 9e80abc..5c02f5e 100644 (file)
@@ -149,7 +149,7 @@ Ext.extend(Tine.Tinebase.data.RecordProxy, Ext.data.DataProxy, {
         
         var p = options.params;
         p.method = this.appName + '.get' + this.modelName;
-        p.id = record.get(this.idProperty);
+        p.id = Ext.isString(record) ? record : record.get(this.idProperty);
         
         return this.doXHTTPRequest(options);
     },