-<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>
--- /dev/null
+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;
+});
<?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;
*/
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');
+ }
}
/**
* @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();
// removes orphaned and non-accessible events
UserActivityEventHandler::validateEvents($eventList);
+ if ($this->boxController !== null) {
+ $eventList->truncate($this->boxController->getBox()->limit);
+ }
+
if (!count($eventList)) {
return [];
}
<?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;
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(),
}
else {
return WCF::getTPL()->fetch('boxRecentActivitySidebar', 'wcf', [
+ 'boxID' => $this->getBox()->boxID,
'eventList' => $this->objectList
], true);
}
// 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;
+ }
}