Fixed multiple instances of recent activities
authorAlexander Ebert <ebert@woltlab.com>
Tue, 6 Dec 2016 17:35:29 +0000 (18:35 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 6 Dec 2016 17:35:29 +0000 (18:35 +0100)
com.woltlab.wcf/templates/boxRecentActivity.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Activity/Recent.js [new file with mode: 0644]
wcfsetup/install/files/lib/data/user/activity/event/UserActivityEventAction.class.php
wcfsetup/install/files/lib/system/box/RecentActivityListBoxController.class.php

index 70ed0d93c93c85eb5fc3f492661081cdaba0dcf1..db1bc08e38a713c4be80e8e760d22ea913c20e72 100644 (file)
@@ -1,11 +1,17 @@
-<section class="section sectionContainerList dashboardBoxRecentActivity" id="dashboardBoxRecentActivity">
+<section class="section sectionContainerList dashboardBoxRecentActivity" id="boxRecentActivity{@$boxID}">
        <header class="sectionHeader">
                <h2 class="sectionTitle">{lang}wcf.user.recentActivity{/lang}</h2>
        </header>
        
        {assign var='__events' value=$eventList->getObjects()}
        {assign var='__lastEvent' value=$__events|end}
-       <ul id="recentActivities" class="containerList recentActivityList" data-last-event-time="{@$lastEventTime}" data-last-event-id="{if $__lastEvent}{@$__lastEvent->eventID}{else}0{/if}">
+       <ul class="containerList recentActivityList"
+           data-last-event-time="{@$lastEventTime}"
+           data-last-event-id="{if $__lastEvent}{@$__lastEvent->eventID}{else}0{/if}"
+           data-filtered-by-followed-users="{if $filteredByFollowedUsers}true{else}false{/if}"
+           data-user-id="0"
+           data-box-id="{@$boxID}"
+       >
                {if $canFilterByFollowedUsers}
                        <li class="containerListButtonGroup jsOnly jsRecentActivitySwitchContext">
                                <ul class="buttonGroup">
 </section>
 
 <script data-relocate="true">
-       $(function() {
-               WCF.Language.addObject({
+       require(['Language', 'WoltLabSuite/Core/Ui/User/Activity/Recent'], function (Language, UiUserActivityRecent) {
+               Language.addObject({
                        'wcf.user.recentActivity.more': '{lang}wcf.user.recentActivity.more{/lang}',
                        'wcf.user.recentActivity.noMoreEntries': '{lang}wcf.user.recentActivity.noMoreEntries{/lang}'
                });
                
-               new WCF.User.RecentActivityLoader(null, {if $filteredByFollowedUsers}true{else}false{/if});
+               new UiUserActivityRecent('boxRecentActivity{@$boxID}');
        });
 </script>
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Activity/Recent.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Activity/Recent.js
new file mode 100644 (file)
index 0000000..2bda92c
--- /dev/null
@@ -0,0 +1,86 @@
+define(['Ajax', 'Language', 'Dom/Util'], function(Ajax, Language, DomUtil) {
+       "use strict";
+       
+       function UiUserActivityRecent(containerId) { this.init(containerId); }
+       UiUserActivityRecent.prototype = {
+               init: function (containerId) {
+                       this._containerId = containerId;
+                       var container = elById(this._containerId);
+                       this._list = elBySel('.recentActivityList', container);
+                       
+                       var showMoreItem = elCreate('li');
+                       showMoreItem.className = 'showMore';
+                       if (this._list.childElementCount) {
+                               showMoreItem.innerHTML = '<button class="small">' + Language.get('wcf.user.recentActivity.more') + '</button>';
+                               showMoreItem.children[0].addEventListener(WCF_CLICK_EVENT, this._showMore.bind(this));
+                       }
+                       else {
+                               showMoreItem.innerHTML = '<small>' + Language.get('wcf.user.recentActivity.noMoreEntries') + '</small>';
+                       }
+                       
+                       this._list.appendChild(showMoreItem);
+                       this._showMoreItem = showMoreItem;
+                       
+                       var button = elBySel('.jsRecentActivitySwitchContext button:not(.active)', container);
+                       if (button !== null) {
+                               button.addEventListener(WCF_CLICK_EVENT, this._switchContext.bind(this));
+                       }
+               },
+               
+               _showMore: function (event) {
+                       event.preventDefault();
+                       
+                       this._showMoreItem.children[0].disabled = true;
+                       
+                       Ajax.api(this, {
+                               actionName: 'load',
+                               parameters: {
+                                       boxID: ~~elData(this._list, 'box-id'),
+                                       filteredByFollowedUsers: elDataBool(this._list, 'filtered-by-followed-users'),
+                                       lastEventId: elData(this._list, 'last-event-id'),
+                                       lastEventTime: elData(this._list, 'last-event-time'),
+                                       userID: ~~elData(this._list, 'user-id')
+                               }
+                       });
+               },
+               
+               _switchContext: function(event) {
+                       event.preventDefault();
+                       
+                       Ajax.api(
+                               this,
+                               {
+                                       actionName: 'switchContext'
+                               },
+                               (function () {
+                                       window.location.hash = '#' + this._containerId;
+                                       window.location.reload();
+                               }).bind(this)
+                       );
+               },
+               
+               _ajaxSuccess: function(data) {
+                       if (data.returnValues.template) {
+                               DomUtil.insertHtml(data.returnValues.template, this._showMoreItem, 'before');
+                               
+                               elData(this._list, 'last-event-time', data.returnValues.lastEventTime);
+                               elData(this._list, 'last-event-id', data.returnValues.lastEventID);
+                               
+                               this._showMoreItem.children[0].disabled = false;
+                       }
+                       else {
+                               this._showMoreItem.innerHTML = '<small>' + Language.get('wcf.user.recentActivity.noMoreEntries') + '</small>';
+                       }
+               },
+               
+               _ajaxSetup: function () {
+                       return {
+                               data: {
+                                       className: 'wcf\\data\\user\\activity\\event\\UserActivityEventAction'
+                               }
+                       };
+               }
+       };
+       
+       return UiUserActivityRecent;
+});
index 501d46f5b76480463266e4edde3c697444a27c1d..4911f47302f65d5812fdc133daedafda01201264 100644 (file)
@@ -1,8 +1,11 @@
 <?php
 namespace wcf\data\user\activity\event;
+use wcf\data\box\Box;
 use wcf\data\user\User;
 use wcf\data\user\UserAction;
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\box\RecentActivityListBoxController;
+use wcf\system\exception\UserInputException;
 use wcf\system\user\activity\event\UserActivityEventHandler;
 use wcf\system\WCF;
 
@@ -24,14 +27,33 @@ class UserActivityEventAction extends AbstractDatabaseObjectAction {
         */
        public $allowGuestAccess = ['load'];
        
+       /**
+        * @var RecentActivityListBoxController
+        */
+       public $boxController;
+       
        /**
         * Validates parameters to load recent activity entries.
         */
        public function validateLoad() {
+               $this->readInteger('boxID', true);
                $this->readBoolean('filteredByFollowedUsers', true);
                $this->readInteger('lastEventTime');
                $this->readInteger('lastEventID', true);
                $this->readInteger('userID', true);
+               
+               if ($this->parameters['boxID']) {
+                       $box = new Box($this->parameters['boxID']);
+                       if ($box->boxID) {
+                               $this->boxController = $box->getController();
+                               if ($this->boxController instanceof RecentActivityListBoxController) {
+                                       // all checks passed, end validation; otherwise throw the exception below
+                                       return;
+                               }
+                       }
+                       
+                       throw new UserInputException('boxID');
+               }
        }
        
        /**
@@ -40,25 +62,33 @@ class UserActivityEventAction extends AbstractDatabaseObjectAction {
         * @return      array
         */
        public function load() {
-               $eventList = new ViewableUserActivityEventList();
-               if ($this->parameters['lastEventID']) {
-                       $eventList->getConditionBuilder()->add("user_activity_event.time <= ?", [$this->parameters['lastEventTime']]);
-                       $eventList->getConditionBuilder()->add("user_activity_event.eventID < ?", [$this->parameters['lastEventID']]);
+               $box = null;
+               if ($this->boxController !== null) {
+                       $eventList = $this->boxController->getFilteredList();
+                       
                }
                else {
-                       $eventList->getConditionBuilder()->add("user_activity_event.time < ?", [$this->parameters['lastEventTime']]);
+                       $eventList = new ViewableUserActivityEventList();
+                       
+                       // profile view
+                       if ($this->parameters['userID']) {
+                               $eventList->getConditionBuilder()->add("user_activity_event.userID = ?", [$this->parameters['userID']]);
+                       }
+                       else {
+                               /** @noinspection PhpUndefinedMethodInspection */
+                               if ($this->parameters['filteredByFollowedUsers'] && count(WCF::getUserProfileHandler()->getFollowingUsers())) {
+                                       /** @noinspection PhpUndefinedMethodInspection */
+                                       $eventList->getConditionBuilder()->add('user_activity_event.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
+                               }
+                       }
                }
                
-               // profile view
-               if ($this->parameters['userID']) {
-                       $eventList->getConditionBuilder()->add("user_activity_event.userID = ?", [$this->parameters['userID']]);
+               if ($this->parameters['lastEventID']) {
+                       $eventList->getConditionBuilder()->add("user_activity_event.time <= ?", [$this->parameters['lastEventTime']]);
+                       $eventList->getConditionBuilder()->add("user_activity_event.eventID < ?", [$this->parameters['lastEventID']]);
                }
                else {
-                       /** @noinspection PhpUndefinedMethodInspection */
-                       if ($this->parameters['filteredByFollowedUsers'] && count(WCF::getUserProfileHandler()->getFollowingUsers())) {
-                               /** @noinspection PhpUndefinedMethodInspection */
-                               $eventList->getConditionBuilder()->add('user_activity_event.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
-                       }
+                       $eventList->getConditionBuilder()->add("user_activity_event.time < ?", [$this->parameters['lastEventTime']]);
                }
                
                $eventList->readObjects();
@@ -71,6 +101,10 @@ class UserActivityEventAction extends AbstractDatabaseObjectAction {
                // removes orphaned and non-accessible events
                UserActivityEventHandler::validateEvents($eventList);
                
+               if ($this->boxController !== null) {
+                       $eventList->truncate($this->boxController->getBox()->limit);
+               }
+               
                if (!count($eventList)) {
                        return [];
                }
index c0708a77ccfba425a3e64d4f13f533d9c60cec9a..720adafb8222d4f804252ee1ac535e9b5755ffc6 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 namespace wcf\system\box;
+use wcf\data\box\Box;
 use wcf\data\user\activity\event\ViewableUserActivityEventList;
+use wcf\system\condition\IObjectListCondition;
 use wcf\system\request\LinkHandler;
 use wcf\system\user\activity\event\UserActivityEventHandler;
 use wcf\system\WCF;
@@ -93,6 +95,7 @@ class RecentActivityListBoxController extends AbstractDatabaseObjectListBoxContr
                if ($this->getBox()->position == 'contentTop' || $this->getBox()->position == 'contentBottom') {
                        /** @noinspection PhpUndefinedMethodInspection */
                        return WCF::getTPL()->fetch('boxRecentActivity', 'wcf', [
+                               'boxID' => $this->getBox()->boxID,
                                'canFilterByFollowedUsers' => $this->canFilterByFollowedUsers,
                                'eventList' => $this->objectList,
                                'lastEventTime' => $this->objectList->getLastEventTime(),
@@ -101,6 +104,7 @@ class RecentActivityListBoxController extends AbstractDatabaseObjectListBoxContr
                }
                else {
                        return WCF::getTPL()->fetch('boxRecentActivitySidebar', 'wcf', [
+                               'boxID' => $this->getBox()->boxID,
                                'eventList' => $this->objectList
                        ], true);
                }
@@ -135,4 +139,33 @@ class RecentActivityListBoxController extends AbstractDatabaseObjectListBoxContr
                // remove unused items
                $this->objectList->truncate($this->box->limit);
        }
+       
+       public function getFilteredList() {
+               $this->objectList = $this->getObjectList();
+               
+               if ($this->limit) {
+                       $this->objectList->sqlLimit = $this->box->limit;
+               }
+               
+               if ($this->sortOrder && $this->sortField) {
+                       $alias = $this->objectList->getDatabaseTableAlias();
+                       $this->objectList->sqlOrderBy = $this->sortField . ' ' . $this->sortOrder . ", " . ($alias ? $alias . "." : "") . $this->objectList->getDatabaseTableIndexName() . " " . $this->sortOrder;
+               }
+               
+               if ($this->conditionDefinition) {
+                       foreach ($this->box->getConditions() as $condition) {
+                               /** @var IObjectListCondition $processor */
+                               $processor = $condition->getObjectType()->getProcessor();
+                               $processor->addObjectListCondition($this->objectList, $condition->conditionData);
+                       }
+               }
+               
+               // apply filter
+               if (($this->getBox()->position == 'contentTop' || $this->getBox()->position == 'contentBottom') && $this->filteredByFollowedUsers) {
+                       /** @noinspection PhpUndefinedMethodInspection */
+                       $this->objectList->getConditionBuilder()->add('user_activity_event.userID IN (?)', [WCF::getUserProfileHandler()->getFollowingUsers()]);
+               }
+               
+               return $this->objectList;
+       }
 }