feat(torrents): pagination for torrent seed users and leech users list on torrent detail page

This commit is contained in:
OldHawk
2017-11-10 17:24:52 +08:00
parent 1290c97ea5
commit da35eb3eee
9 changed files with 278 additions and 21 deletions

View File

@@ -736,6 +736,7 @@ module.exports = {
* @adminUserListPerPage: admin manage users list page settings
* @collectionsListPerPage: movie collections list page settings
* @backupFilesListPerPage: system backup files list page settings
* @torrentPeersListPerPage: torrent detail seeder & leecher users list page settings
*/
itemsPerPage: {
topicsPerPage: 10,
@@ -747,7 +748,8 @@ module.exports = {
tracesPerPage: 30,
adminUserListPerPage: 15,
collectionsListPerPage: 6,
backupFilesListPerPage: 15
backupFilesListPerPage: 15,
torrentPeersListPerPage: 15
},
/**

View File

@@ -265,7 +265,7 @@
TAB_TORRENT_INFO: 'Torrent Info',
TAB_USER_SUBTITLE: 'Subtitle Info',
TAB_THUMBS_LIST: 'Thumbs-up',
TAB_USER_INFO: 'User Info',
TAB_USER_INFO: 'Users Info',
TAB_OTHER_TORRENTS: 'Other Torrents',
TAB_MY_PANEL: 'My Pannel',
TAB_ADMIN_PANEL: 'Admin Panel',

View File

@@ -873,6 +873,7 @@ body {
.tb-peers {
background-color: #fff;
margin-bottom: 10px !important;
thead {
tr {
th {
@@ -889,6 +890,9 @@ body {
}
margin-bottom: 0;
}
.pagination {
margin: 0 !important;
}
}
.tb-other-torrents {

View File

@@ -130,6 +130,7 @@
vm.rating_vote = res.resource_detail_info.vote_average;
vm.initTabLists();
vm.commentBuildPager();
vm.buildPeersPager();
if (!vm.announce.privateTorrentCmsMode && vm.scrapeConfig.onTorrentInDetail) {
ScrapeService.scrapeTorrent(vm.torrentLocalInfo);
}
@@ -1137,5 +1138,106 @@
}
});
};
/**
* buildPeersPager
*/
vm.buildPeersPager = function () {
vm.seederPagedItems = [];
vm.leecherPagedItems = [];
vm.peerItemsPerPage = vm.itemsPerPageConfig.torrentPeersListPerPage;
vm.currentSeederPage = 1;
vm.currentLeecherPage = 1;
vm.figureOutSeederItemsToDisplay();
vm.figureOutLeecherItemsToDisplay();
};
/**
* figureOutSeederItemsToDisplay
* @param callback
*/
vm.figureOutSeederItemsToDisplay = function (callback) {
vm.getSeederUsers(vm.currentSeederPage, function (items) {
vm.seederFilterLength = items.total;
vm.seederPagedItems = items.rows;
if (callback) callback();
});
};
/**
* figureOutLeecherItemsToDisplay
* @param callback
*/
vm.figureOutLeecherItemsToDisplay = function (callback) {
vm.getLeecherUsers(vm.currentLeecherPage, function (items) {
vm.leecherFilterLength = items.total;
vm.leecherPagedItems = items.rows;
if (callback) callback();
});
};
/**
* getSeederUsers
* @param p
* @param callback
*/
vm.getSeederUsers = function (p, callback) {
TorrentsService.getSeederUsers({
torrentId: vm.torrentLocalInfo._id,
skip: (p - 1) * vm.peerItemsPerPage,
limit: vm.peerItemsPerPage
}, function (data) {
mtDebug.info(data);
callback(data);
});
};
/**
* getLeecherUsers
* @param p
* @param callback
*/
vm.getLeecherUsers = function (p, callback) {
TorrentsService.getLeecherUsers({
torrentId: vm.torrentLocalInfo._id,
skip: (p - 1) * vm.peerItemsPerPage,
limit: vm.peerItemsPerPage
}, function (data) {
mtDebug.info(data);
callback(data);
});
};
/**
* seederPageChanged
*/
vm.seederPageChanged = function () {
var element = angular.element('#top_of_seeder_list');
vm.figureOutSeederItemsToDisplay(function () {
$timeout(function () {
$('html,body').animate({scrollTop: element[0].offsetTop - 60}, 200);
}, 10);
});
};
/**
* seederPageChanged
*/
vm.leecherPageChanged = function () {
var element = angular.element('#top_of_leecher_list');
vm.figureOutLeecherItemsToDisplay(function () {
$timeout(function () {
$('html,body').animate({scrollTop: element[0].offsetTop - 60}, 200);
}, 10);
});
};
}
}());

View File

@@ -99,6 +99,20 @@
siteInfo: {
method: 'GET',
url: '/api/torrents/siteInfo'
},
getSeederUsers: {
method: 'GET',
url: '/api/torrents/:torrentId/seederUsers',
params: {
torrentId: '@_id'
}
},
getLeecherUsers: {
method: 'GET',
url: '/api/torrents/:torrentId/leecherUsers',
params: {
torrentId: '@_id'
}
}
});

View File

@@ -708,7 +708,7 @@
<dt class="h-line text-left">{{ 'TORRENT_FINISHED_USERS' | translate}}{{vm.torrentLocalInfo.torrent_finished}}</dt>
<dd class="h-line"></dd>
</dl>
<dl class="dl-horizontal">
<dl class="dl-horizontal" id="top_of_seeder_list">
<dt class="h-line">{{ 'TORRENT_SEED_USERS' | translate}}{{vm.torrentLocalInfo.torrent_seeds}}</dt>
<dd class="h-line"></dd>
</dl>
@@ -725,15 +725,15 @@
<th class="text-center">{{ 'TABLE_FIELDS.STARTED' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.ACTIVE' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.CLIENT' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.CONNECTABLE' | translate}}</th>
<!--<th class="text-center">{{ 'TABLE_FIELDS.CONNECTABLE' | translate}}</th>-->
</tr>
</thead>
<tbody>
<tr class="torrent-list-info" ng-repeat="item in vm.torrentLocalInfo._peers | orderBy: peer_uploaded"
<tr class="torrent-list-info" ng-repeat="item in vm.seederPagedItems"
ng-if="item.peer_status == 'seeder'">
<td class="text-center">
<span user-info="item.user" info-name></span>
<span vip-flag="item.user"></span>
<!--<span vip-flag="item.user"></span>-->
<!--<span message-to="item.user" to-class="message-to-icon"></span>-->
</td>
<td class="text-center">{{item.peer_uploaded | bytes:2}} | {{item.peer_uspeed | bytes:2}}/s</td>
@@ -743,13 +743,19 @@
<td class="text-center">{{item.startedat | life}}</td>
<td class="text-center">{{item.last_announce_at | life}}</td>
<td class="text-center">{{item.user_agent}}</td>
<td class="text-center">{{item.peer_connectable}}</td>
<!--<td class="text-center">{{item.peer_connectable}}</td>-->
</tr>
</tbody>
</table>
</div>
<dl class="dl-horizontal">
<ul uib-pagination boundary-links="true" max-size="8" items-per-page="vm.peerItemsPerPage" total-items="vm.seederFilterLength" ng-model="vm.currentSeederPage"
ng-change="vm.seederPageChanged()"
first-text="{{ 'PAGE_TEXT_FIRST' | translate}}" previous-text="{{ 'PAGE_TEXT_PREVIOUS' | translate}}"
next-text="{{ 'PAGE_TEXT_NEXT' | translate}}" last-text="{{ 'PAGE_TEXT_LAST' | translate}}">
</ul>
<dl class="dl-horizontal" id="top_of_leecher_list">
<dt class="h-line">{{ 'TORRENT_LEECHER_USERS' | translate}}{{vm.torrentLocalInfo.torrent_leechers}}</dt>
<dd class="h-line"></dd>
</dl>
@@ -766,15 +772,15 @@
<th class="text-center">{{ 'TABLE_FIELDS.STARTED' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.ACTIVE' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.CLIENT' | translate}}</th>
<th class="text-center">{{ 'TABLE_FIELDS.CONNECTABLE' | translate}}</th>
<!--<th class="text-center">{{ 'TABLE_FIELDS.CONNECTABLE' | translate}}</th>-->
</tr>
</thead>
<tbody>
<tr class="torrent-list-info" ng-repeat="item in vm.torrentLocalInfo._peers | orderBy: peer_downloaded"
<tr class="torrent-list-info" ng-repeat="item in vm.leecherPagedItems"
ng-if="item.peer_status == 'leecher'">
<td class="text-center">
<span user-info="item.user" info-name></span>
<span vip-flag="item.user"></span>
<!--<span vip-flag="item.user"></span>-->
<!--<span message-to="item.user" to-class="message-to-icon"></span>-->
</td>
<td class="text-center">{{item.peer_uploaded | bytes:2}} | {{item.peer_uspeed | bytes:2}}/s</td>
@@ -784,11 +790,17 @@
<td class="text-center">{{item.startedat | life}}</td>
<td class="text-center">{{item.last_announce_at | life}}</td>
<td class="text-center">{{item.user_agent}}</td>
<td class="text-center">{{item.peer_connectable}}</td>
<!--<td class="text-center">{{item.peer_connectable}}</td>-->
</tr>
</tbody>
</table>
</div>
<ul uib-pagination boundary-links="true" max-size="8" items-per-page="vm.peerItemsPerPage" total-items="vm.leecherFilterLength" ng-model="vm.currentLeecherPage"
ng-change="vm.leecherPageChanged()"
first-text="{{ 'PAGE_TEXT_FIRST' | translate}}" previous-text="{{ 'PAGE_TEXT_PREVIOUS' | translate}}"
next-text="{{ 'PAGE_TEXT_NEXT' | translate}}" last-text="{{ 'PAGE_TEXT_LAST' | translate}}">
</ul>
</div>
</script>

View File

@@ -1440,6 +1440,124 @@ exports.siteInfo = function (req, res) {
});
};
/**
* getSeederUsers
* @param req
* @param res
*/
exports.getSeederUsers = function (req, res) {
var skip = 0;
var limit = 0;
if (req.query.skip !== undefined) {
skip = parseInt(req.query.skip, 10);
}
if (req.query.limit !== undefined) {
limit = parseInt(req.query.limit, 10);
}
var countSeederUsers = function (callback) {
Peer.count({
torrent: req.torrent._id,
peer_status: PEERSTATE_SEEDER
}, function (err, count) {
if (err) {
callback(err, null);
} else {
callback(null, count);
}
});
};
var findSeederUsers = function (callback) {
Peer.find({
torrent: req.torrent._id,
peer_status: PEERSTATE_SEEDER
})
.sort('-peer_uploaded')
.populate('user', 'username displayName profileImageURL isVip')
.skip(skip)
.limit(limit)
.exec(function (err, peers) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
callback(null, peers);
}
});
};
async.parallel([countSeederUsers, findSeederUsers], function (err, results) {
if (err) {
return res.status(422).send(err);
} else {
res.json({rows: results[1], total: results[0]});
}
});
};
/**
* getLeecherUsers
* @param req
* @param res
*/
exports.getLeecherUsers = function (req, res) {
var skip = 0;
var limit = 0;
if (req.query.skip !== undefined) {
skip = parseInt(req.query.skip, 10);
}
if (req.query.limit !== undefined) {
limit = parseInt(req.query.limit, 10);
}
var countSeederUsers = function (callback) {
Peer.count({
torrent: req.torrent._id,
peer_status: PEERSTATE_LEECHER
}, function (err, count) {
if (err) {
callback(err, null);
} else {
callback(null, count);
}
});
};
var findSeederUsers = function (callback) {
Peer.find({
torrent: req.torrent._id,
peer_status: PEERSTATE_LEECHER
})
.sort('-peer_uploaded')
.populate('user', 'username displayName profileImageURL isVip')
.skip(skip)
.limit(limit)
.exec(function (err, peers) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
callback(null, peers);
}
});
};
async.parallel([countSeederUsers, findSeederUsers], function (err, results) {
if (err) {
return res.status(422).send(err);
} else {
res.json({rows: results[1], total: results[0]});
}
});
};
/**
* Torrent middleware
*/
@@ -1452,7 +1570,7 @@ exports.torrentByID = function (req, res, next, id) {
}
var findTorrents = function (callback) {
Torrent.findById(id)
Torrent.find({_id: id}, {'_peers': 0})
.populate('user', 'username displayName profileImageURL isVip')
.populate('maker', 'name')
.populate('_thumbs.user', 'username displayName profileImageURL isVip uploaded downloaded')
@@ -1474,20 +1592,13 @@ exports.torrentByID = function (req, res, next, id) {
select: 'username displayName profileImageURL isVip'
}
})
.populate({
path: '_peers',
populate: {
path: 'user',
select: 'username displayName profileImageURL isVip'
}
})
.exec(function (err, torrent) {
if (err) {
callback(err);
} else if (!torrent) {
callback(new Error('No torrent with that id has been found'));
}
callback(null, torrent);
callback(null, torrent[0]);
});
};

View File

@@ -29,6 +29,8 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/torrents/:torrentId/thumbsUp', permissions: '*'},
{resources: '/api/torrents/:torrentId/rating', permissions: '*'},
{resources: '/api/torrents/:torrentId/scrape', permissions: '*'},
{resources: '/api/torrents/:torrentId/seederUsers', permissions: '*'},
{resources: '/api/torrents/:torrentId/leecherUsers', permissions: '*'},
{resources: '/api/torrents/:torrentId/toggleHnRStatus', permissions: '*'},
{resources: '/api/torrents/:torrentId/toggleVIPStatus', permissions: '*'},
{resources: '/api/torrents/:torrentId/set/saletype/:saleType', permissions: '*'},
@@ -65,6 +67,8 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/torrents/:torrentId/thumbsUp', permissions: ['put']},
{resources: '/api/torrents/:torrentId/rating', permissions: ['put']},
{resources: '/api/torrents/:torrentId/scrape', permissions: ['get']},
{resources: '/api/torrents/:torrentId/seederUsers', permissions: ['get']},
{resources: '/api/torrents/:torrentId/leecherUsers', permissions: ['get']},
{resources: '/api/subtitles/:torrentId', permissions: ['post']},
{resources: '/api/subtitles/:torrentId/:subtitleId', permissions: ['get', 'delete']},
@@ -88,6 +92,8 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/tvinfo/:tmdbid/:language', permissions: ['get']},
{resources: '/api/torrents', permissions: ['get']},
{resources: '/api/torrents/:torrentId', permissions: ['get']},
{resources: '/api/torrents/:torrentId/seederUsers', permissions: ['get']},
{resources: '/api/torrents/:torrentId/leecherUsers', permissions: ['get']},
{resources: '/api/torrents/siteInfo', permissions: ['get']}
]
}

View File

@@ -49,6 +49,12 @@ module.exports = function (app) {
app.route('/api/torrents/:torrentId/scrape').all(torrentsPolicy.isAllowed)
.get(torrents.scrape);
app.route('/api/torrents/:torrentId/seederUsers').all(torrentsPolicy.isAllowed)
.get(torrents.getSeederUsers);
app.route('/api/torrents/:torrentId/leecherUsers').all(torrentsPolicy.isAllowed)
.get(torrents.getLeecherUsers);
app.route('/api/torrents/:torrentId/toggleHnRStatus').all(torrentsPolicy.isAllowed)
.put(torrents.toggleHnRStatus);