feat(history): show user account history on manage page

This commit is contained in:
OldHawk
2018-05-29 18:05:10 +08:00
parent 330f0c5406
commit 37cd2887fe
14 changed files with 151 additions and 44 deletions

View File

@@ -1017,7 +1017,9 @@
CURR_LEECHED_IP: 'Latest leeched IP',
BT_CLIENT: 'Leeched BT Client list',
ADMIN_REMARKS: 'Admin Remarks',
BTN_SAVE_REMARKS: 'Save remarks'
BTN_SAVE_REMARKS: 'Save remarks',
ADMIN_HISTORY: 'Operate history',
ADMIN_VIEW_HISTORY: 'View history'
},
TORRENT_TYPE_LABEL: {
MOVIE: 'Movie',
@@ -1716,14 +1718,14 @@
//admin operate user account history message
HISTORY: {
ADMIN_UPDATE_USER_ROLE: '{{by}} update account role to: {{role}}',
ADMIN_UPDATE_USER_STATUS: '{{by}} update account status to: {{status}}',
ADMIN_UPDATE_USER_SCORE: '{{by}} update account score: {{score}}',
ADMIN_UPDATE_USER_UPLOADED: '{{by}} update account uploaded: {{uploaded}}',
ADMIN_UPDATE_USER_DOWNLOADED: '{{by}} update account downloaded: {{downloaded}}',
ADMIN_UPDATE_USER_VIP_DATA: '{{by}} update account vip data: {{months}} months',
ADMIN_PRESENT_USER_INVITATIONS: '{{by}} present {{numbers}} official invitations, expires {{days}} days',
ADMIN_REMOVE_USER_HNR_WARNING: '{{by}} remove H&R warning, complete id: {{complete}}'
ADMIN_UPDATE_USER_ROLE: '`{{by.displayName}}` update account role to: `{{role}}`',
ADMIN_UPDATE_USER_STATUS: '`{{by.displayName}}` update account status to: `{{status}}`',
ADMIN_UPDATE_USER_SCORE: '`{{by.displayName}}` update account score: `{{score}}`',
ADMIN_UPDATE_USER_UPLOADED: '`{{by.displayName}}` update account uploaded: `{{uploaded | bytes:2}}`',
ADMIN_UPDATE_USER_DOWNLOADED: '`{{by.displayName}}` update account downloaded: `{{downloaded | bytes:2}}`',
ADMIN_UPDATE_USER_VIP_DATA: '`{{by.displayName}}` update account vip data: `{{months}}` months',
ADMIN_PRESENT_USER_INVITATIONS: '`{{by.displayName}}` present `{{numbers}}` official invitations, expires `{{days}}` days',
ADMIN_REMOVE_USER_HNR_WARNING: '`{{by.displayName}}` remove H&R warning, complete id: `{{complete}}`'
},
//server returned string

View File

@@ -1017,7 +1017,9 @@
CURR_LEECHED_IP: '最近一次下載IP',
BT_CLIENT: '下載過的BT客戶端',
ADMIN_REMARKS: '管理員備註',
BTN_SAVE_REMARKS: '保存備註'
BTN_SAVE_REMARKS: '保存備註',
ADMIN_HISTORY: '管理員操作歷史',
ADMIN_VIEW_HISTORY: '查看歷史'
},
TORRENT_TYPE_LABEL: {
MOVIE: '電影',
@@ -1716,14 +1718,14 @@
//admin operate user account history message
HISTORY: {
ADMIN_UPDATE_USER_ROLE: '{{by}} 改變帳戶角色為: {{role}}',
ADMIN_UPDATE_USER_STATUS: '{{by}} 改變帳戶狀態為: {{status}}',
ADMIN_UPDATE_USER_SCORE: '{{by}} 修改帳戶積分: {{score}}',
ADMIN_UPDATE_USER_UPLOADED: '{{by}} 修改帳戶上傳量: {{uploaded}}',
ADMIN_UPDATE_USER_DOWNLOADED: '{{by}} 修改帳戶下載量: {{downloaded}}',
ADMIN_UPDATE_USER_VIP_DATA: '{{by}} 修改帳戶 VIP 數據: {{months}} 個月',
ADMIN_PRESENT_USER_INVITATIONS: '{{by}} 贈送 {{numbers}} 個官方邀請函, 有效期 {{days}} 天',
ADMIN_REMOVE_USER_HNR_WARNING: '{{by}} 移除 H&R 警告, complete id: {{complete}}'
ADMIN_UPDATE_USER_ROLE: '`{{by.displayName}}` 改變帳戶角色為: `{{role}}`',
ADMIN_UPDATE_USER_STATUS: '`{{by.displayName}}` 改變帳戶狀態為: `{{status}}`',
ADMIN_UPDATE_USER_SCORE: '`{{by.displayName}}` 修改帳戶積分: `{{score}}`',
ADMIN_UPDATE_USER_UPLOADED: '`{{by.displayName}}` 修改帳戶上傳量: `{{uploaded | bytes:2}}`',
ADMIN_UPDATE_USER_DOWNLOADED: '`{{by.displayName}}` 修改帳戶下載量: `{{downloaded | bytes:2}}`',
ADMIN_UPDATE_USER_VIP_DATA: '`{{by.displayName}}` 修改帳戶 VIP 數據: `{{months}}` 個月',
ADMIN_PRESENT_USER_INVITATIONS: '`{{by.displayName}}` 贈送 `{{numbers}}` 個官方邀請函, 有效期 `{{days}}` 天',
ADMIN_REMOVE_USER_HNR_WARNING: '`{{by.displayName}}` 移除 H&R 警告, complete id: `{{complete}}`'
},
//server returned string

View File

@@ -1017,7 +1017,9 @@
CURR_LEECHED_IP: '最近一次下载IP',
BT_CLIENT: '下载过的BT客户端',
ADMIN_REMARKS: '管理员备注',
BTN_SAVE_REMARKS: '保存备注'
BTN_SAVE_REMARKS: '保存备注',
ADMIN_HISTORY: '管理员操作历史',
ADMIN_VIEW_HISTORY: '查看历史'
},
TORRENT_TYPE_LABEL: {
MOVIE: '电影',
@@ -1716,14 +1718,14 @@
//admin operate user account history message
HISTORY: {
ADMIN_UPDATE_USER_ROLE: '{{by}} 改变帐户角色为: {{role}}',
ADMIN_UPDATE_USER_STATUS: '{{by}} 改变帐户状态为: {{status}}',
ADMIN_UPDATE_USER_SCORE: '{{by}} 修改帐户积分: {{score}}',
ADMIN_UPDATE_USER_UPLOADED: '{{by}} 修改帐户上传量: {{uploaded}}',
ADMIN_UPDATE_USER_DOWNLOADED: '{{by}} 修改帐户下载量: {{downloaded}}',
ADMIN_UPDATE_USER_VIP_DATA: '{{by}} 修改帐户 VIP 数据: {{months}} 个月',
ADMIN_PRESENT_USER_INVITATIONS: '{{by}} 赠送 {{numbers}} 个官方邀请函, 有效期 {{days}} 天',
ADMIN_REMOVE_USER_HNR_WARNING: '{{by}} 移除 H&R 警告, complete id: {{complete}}'
ADMIN_UPDATE_USER_ROLE: '`{{by.displayName}}` 改变帐户角色为: `{{role}}`',
ADMIN_UPDATE_USER_STATUS: '`{{by.displayName}}` 改变帐户状态为: `{{status}}`',
ADMIN_UPDATE_USER_SCORE: '`{{by.displayName}}` 修改帐户积分: `{{score}}`',
ADMIN_UPDATE_USER_UPLOADED: '`{{by.displayName}}` 修改帐户上传量: `{{uploaded | bytes:2}}`',
ADMIN_UPDATE_USER_DOWNLOADED: '`{{by.displayName}}` 修改帐户下载量: `{{downloaded | bytes:2}}`',
ADMIN_UPDATE_USER_VIP_DATA: '`{{by.displayName}}` 修改帐户 VIP 数据: `{{months}}` 个月',
ADMIN_PRESENT_USER_INVITATIONS: '`{{by.displayName}}` 赠送 `{{numbers}}` 个官方邀请函, 有效期 `{{days}}` 天',
ADMIN_REMOVE_USER_HNR_WARNING: '`{{by.displayName}}` 移除 H&R 警告, complete id: `{{complete}}`'
},
//server returned string

View File

@@ -118,6 +118,10 @@
padding-top: 10px;
}
.padding-top-15 {
padding-top: 15px;
}
.padding-top-20 {
padding-top: 20px;
}
@@ -146,6 +150,10 @@
padding-bottom: 10px;
}
.padding-bottom-15 {
padding-bottom: 15px;
}
.padding-bottom-20 {
padding-bottom: 20px;
}

View File

@@ -6,10 +6,12 @@
.controller('UserController', UserController);
UserController.$inject = ['$scope', '$state', '$window', 'Authentication', 'userResolve', 'Notification', 'NotifycationService', 'MeanTorrentConfig',
'AdminService', 'ScoreLevelService', 'DebugConsoleService', 'TorrentGetInfoServices', 'SideOverlay', 'MakerGroupService'];
'AdminService', 'ScoreLevelService', 'DebugConsoleService', 'TorrentGetInfoServices', 'SideOverlay', 'MakerGroupService', '$filter', '$translate',
'marked'];
function UserController($scope, $state, $window, Authentication, user, Notification, NotifycationService, MeanTorrentConfig,
AdminService, ScoreLevelService, mtDebug, TorrentGetInfoServices, SideOverlay, MakerGroupService) {
AdminService, ScoreLevelService, mtDebug, TorrentGetInfoServices, SideOverlay, MakerGroupService, $filter, $translate,
marked) {
var vm = this;
vm.TGI = TorrentGetInfoServices;
vm.authentication = Authentication;
@@ -62,6 +64,15 @@
mtDebug.info(vm.user);
/**
* $watch 'vm.user'
*/
$scope.$watch('vm.user', function (newValue, oldValue) {
if (vm.user) {
vm.getUserHistory();
}
});
/**
* remove
* @param user
@@ -466,5 +477,29 @@
});
};
/**
* getUserHistory
*/
vm.getUserHistory = function () {
AdminService.userHistory({
userId: user._id
}).then(function (res) {
vm.historyList = res;
});
};
/**
* getHistoryContent
* @param h
* @returns {string}
*/
vm.getHistoryContent = function (h) {
var time = $filter('date')(h.createdAt, 'yyyy-MM-dd HH:mm');
var con = $translate.instant('HISTORY.' + h.event_str, h.params);
var res = time + ' - ' + con;
return marked(res, {sanitize: false});
};
}
}());

View File

@@ -31,4 +31,17 @@
display: table-row !important;
float: none !important;
}
}
.user-remarks {
textarea {
min-height: 150px;
line-height: 0.8;
resize: vertical;
}
}
.user-history {
height: 150px;
line-height: 0.8;
overflow-y: scroll;
}

View File

@@ -325,6 +325,14 @@
params: {
userId: '@userId'
}
},
getUserHistory: {
method: 'GET',
isArray: true,
url: '/api/users/:userId/history',
params: {
userId: '@userId'
}
}
});
@@ -361,6 +369,9 @@
},
presentUserInvitations: function (params) {
return this.presentInvitations(params).$promise;
},
userHistory: function (params) {
return this.getUserHistory(params).$promise;
}
});

View File

@@ -18,8 +18,8 @@
{{'BTN_PRESENT_INVITATIONS' | translate}}
</button>
<!--<a class="btn btn-primary btn-width-80" ui-sref="admin.user-edit({userId: vm.user._id})"-->
<!--ng-if="vm.authentication.user.isAdmin">-->
<!--{{ 'STATUS_FIELD.BTN_EDIT' | translate}}-->
<!--ng-if="vm.authentication.user.isAdmin">-->
<!--{{ 'STATUS_FIELD.BTN_EDIT' | translate}}-->
<!--</a>-->
<a class="btn btn-primary btn-width-80" ng-click="vm.remove()" ng-if="!vm.isContextUserSelf() && !vm.user.isOper">
{{ 'STATUS_FIELD.BTN_REMOVE' | translate}}
@@ -285,10 +285,17 @@
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.ADMIN_HISTORY' | translate}}</dt>
<dd class="h-line" ng-init="vm.getUserHistory()">
<div class="form-control user-history padding-top-15 padding-bottom-15 margin-top-10 margin-bottom-10">
<p ng-repeat="h in vm.historyList | orderBy: '-createdAt'" ng-bind-html="vm.getHistoryContent(h)"></p>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.ADMIN_REMARKS' | translate}}</dt>
<dd class="h-line">
<div class="padding-top-10 padding-bottom-10">
<textarea class="form-control" rows="8" ng-model="vm.user.remarks"></textarea>
<div class="user-remarks padding-top-10 padding-bottom-10">
<textarea class="form-control" ng-model="vm.user.remarks"></textarea>
<button class="btn btn-default btn-width-100 margin-top-10"
ng-click="vm.saveRemarks()">
{{'STATUS_FIELD.BTN_SAVE_REMARKS' | translate}}

View File

@@ -27,7 +27,7 @@ module.exports = function () {
}, {
email: usernameOrEmail.toLowerCase()
}]
}, '-remarks').populate('invited_by', 'username displayName profileImageURL isVip score uploaded downloaded')
}, '-history -remarks').populate('invited_by', 'username displayName profileImageURL isVip score uploaded downloaded')
.populate('makers', 'name')
.exec(function (err, user) {
if (err) {

View File

@@ -22,7 +22,7 @@ module.exports = function (app) {
passport.deserializeUser(function (id, done) {
User.findOne({
_id: id
}, '-salt -password -remarks')
}, '-salt -password -history -remarks')
.populate('invited_by', 'username displayName profileImageURL isVip score uploaded downloaded')
.populate('makers', 'name').exec(function (err, user) {
done(err, user);

View File

@@ -292,11 +292,11 @@ exports.updateUserStatus = function (req, res) {
user: user._id,
status: req.body.userStatus
});
//write history
// history.insert(user._id, historyConfig.action.adminUpdateUserStatus, {
// status: req.body.userStatus,
// by: req.user._id
// });
// write history
history.insert(user._id, historyConfig.action.adminUpdateUserStatus, {
status: req.body.userStatus,
by: req.user._id
});
}
});
};
@@ -625,6 +625,31 @@ exports.presentInvitations = function (req, res) {
});
};
/**
* getUserHistory
* @param req
* @param res
*/
exports.getUserHistory = function (req, res) {
var user = req.model;
User.findById(user._id, 'history')
.populate({
path: 'history.params.by',
model: 'User',
select: 'displayName'
})
.exec(function (err, his) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(his.history);
}
});
};
/**
* list user seeding torrents
* @param req
@@ -750,7 +775,6 @@ exports.resetUserProfileImage = function (req, res) {
}
res.json(user);
});
};
@@ -764,7 +788,7 @@ exports.userByID = function (req, res, next, id) {
});
}
User.findById(id, '-salt -password -providerData')
User.findById(id, '-salt -password -providerData -history')
.populate('invited_by', 'username displayName profileImageURL isVip score uploaded downloaded')
.populate('makers', 'user name')
.exec(function (err, user) {

View File

@@ -19,7 +19,7 @@ exports.userByID = function (req, res, next, id) {
User.findOne({
_id: id
}, '-remarks')
}, '-history -remarks')
.populate('invited_by', 'username displayName profileImageURL isVip score uploaded downloaded')
.populate('makers', 'name')
.exec(function (err, user) {

View File

@@ -39,7 +39,8 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/users/:userId/uptotal', permissions: '*'},
{resources: '/api/users/:userId/followers', permissions: '*'},
{resources: '/api/users/:userId/following', permissions: '*'},
{resources: '/api/users/:userId/resetImage', permissions: '*'}
{resources: '/api/users/:userId/resetImage', permissions: '*'},
{resources: '/api/users/:userId/history', permissions: '*'}
]
},
{

View File

@@ -52,6 +52,8 @@ module.exports = function (app) {
.put(admin.resetUserProfileImage);
app.route('/api/users/:userId/presentInvitations').all(adminPolicy.isAllowed)
.put(admin.presentInvitations);
app.route('/api/users/:userId/history')
.get(admin.getUserHistory);
app.route('/api/users/:userId/VIPMonths/reset').all(adminPolicy.isAllowed)
.put(admin.resetVIPData);