feat(medals): new module medals

This commit is contained in:
OldHawk
2018-06-18 20:32:11 +08:00
parent 70cd5c2a55
commit 18dbdf50b1
126 changed files with 12789 additions and 1124 deletions

172
config/env/torrents.js vendored
View File

@@ -167,8 +167,7 @@ module.exports = {
debugAnnounceUser: {
debugAll: false,
ids: [
'59227f9095602327ea1d96ba',
'592280c464be9e281a1ec56e'
'59227f9095602327ea1d96ba'
]
},
debugClientSideUser: {
@@ -334,6 +333,128 @@ module.exports = {
]
},
/**
* @medals
*
* settings of medals wall
*
* @showWorkerUsersListToAll: setting normal user whether can list workers type medal owned users
* @type: medals type
* @cats: medal cats, please add translate string MEDALS_CATS_@cats
* @name: medal name
* @prefix: medal description translate string prefix, such as MEDALS_DESC_@prifix
* @faClass: medal logo background layer icon class with font-awesome
* @iconClass: medal logo top icon class with font-awesome
*
* @hasHeader: setting whether has a header string on medal, if true please add translate string MEDALS_HEADERSTRING_@prefix
* @hasFooter: setting whether has a footer string on medal, if true please add translate string MEDALS_FOOTERSTRING_@prefix
* @passHelp: setting for get this medal need who help
* @score: setting for self help medal by scores number
* @enable: enable status
*/
medals: {
showWorkerUsersListToAll: false,
type: [
{
cats: 'workers', name: 'root', prefix: 'ROOT', faClass: 'fa fa-shield', iconClass: 'far fa-user-secret',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'networkAdmin', prefix: 'NETWORK_ADMIN', faClass: 'fa fa-shield', iconClass: 'far fa-user-graduate',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'supportAdmin', prefix: 'SUPPORT_ADMIN', faClass: 'fa fa-shield', iconClass: 'far fa-user-graduate',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'forumAdmin', prefix: 'FORUM_ADMIN', faClass: 'fa fa-shield', iconClass: 'far fa-user-graduate',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'resourceAdmin', prefix: 'RESOURCE_ADMIN', faClass: 'fa fa-shield', iconClass: 'far fa-user-graduate',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'ambassador', prefix: 'AMBASSADOR', faClass: 'fa fa-shield', iconClass: 'far fa-user-tie',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'forumModerators', prefix: 'FORUM_MODERATORS', faClass: 'fa fa-shield', iconClass: 'far fa-address-card',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'makerFounder', prefix: 'MAKER_FOUNDER', faClass: 'fa fa-shield', iconClass: 'far fa-user-tag',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'uploader', prefix: 'UPLOADER', faClass: 'fa fa-shield', iconClass: 'far fa-user-ninja',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'workers', name: 'retiree', prefix: 'RETIREE', faClass: 'fa fa-shield', iconClass: 'far fa-wheelchair',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'users', name: 'beauty3000', prefix: 'BEAUTY_3000', faClass: 'fa fa-ticket', iconClass: 'far fa-users',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'users', name: 'roam', prefix: 'ROAM', faClass: 'fa fa-ticket', iconClass: 'far fa-user-astronaut',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'users', name: 'noExamination', prefix: 'NO_EXAMINATION', faClass: 'fa fa-ticket', iconClass: 'far fa-user-check',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'users', name: 'slugger', prefix: 'SLUGGER', faClass: 'fa fa-ticket', iconClass: 'far fa-child',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'users', name: 'elder', prefix: 'ELDER', faClass: 'fa fa-ticket', iconClass: 'far fa-blind',
hasHeader: false, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'vip', name: 'foreverVip', prefix: 'FOREVER_VIP', faClass: 'fa fa-bookmark',
hasHeader: true, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'vip', name: 'yearlyVip', prefix: 'YEARLY_VIP', faClass: 'fa fa-bookmark',
hasHeader: true, hasFooter: true, passHelp: 'sys', enable: true
},
{
cats: 'vip', name: 'monthlyVip', prefix: 'MONTHLY_VIP', faClass: 'fa fa-bookmark',
hasHeader: true, hasFooter: true, passHelp: 'sys', enable: true
},
{
cats: 'vip', name: 'guestVip', prefix: 'GUEST_VIP', faClass: 'fa fa-bookmark',
hasHeader: true, hasFooter: true, passHelp: 'admin', enable: true
},
{
cats: 'commemorative', name: 'siteBegin', prefix: 'SITE_BEGIN', faClass: 'fa fa-badge',
hasHeader: true, hasFooter: true, passHelp: 'self', score: 1000, enable: true
},
{
cats: 'commemorative', name: 'forOneYears', prefix: 'FOR_ONE_YEARS', faClass: 'fa fa-badge',
hasHeader: true, hasFooter: true, passHelp: 'self', score: 10000, enable: true
},
{
cats: 'commemorative', name: 'forTwoYears', prefix: 'FOR_TWO_YEARS', faClass: 'fa fa-badge',
hasHeader: true, hasFooter: true, passHelp: 'self', score: 20000, enable: true
},
{
cats: 'events', name: 'eventName', prefix: 'EVENT_NAME', faClass: 'fa fa-hexagon',
hasHeader: true, hasFooter: true, passHelp: 'admin', enable: true
}
]
},
/**
* @sign
*
@@ -495,6 +616,7 @@ module.exports = {
scoreExchangeInvitation: {name: 'scoreExchangeInvitation', content: 'SCORE_EXCHANGE_INVITATION', value: 0, enable: true}, //value used invite.scoreExchange
scoreToRemoveWarning: {name: 'scoreToRemoveWarning', content: 'SCORETO_REMOVE_WARNING', value: 0, enable: true}, //value used hitAndRun.scoreToRemoveWarning
scoreToRequestMedal: {name: 'scoreToRequestMedal', content: 'SCORETO_REQUEST_MEDAL', value: 0, enable: true}, //value used hitAndRun.scoreToRemoveWarning
activeIdleAccount: {name: 'activeIdleAccount', content: 'ACTIVE_IDLE_ACCOUNT', value: 0, enable: true}, //value used sign.idle.activeIdleAccountBasicScore
dailyCheckIn: {
@@ -714,6 +836,8 @@ module.exports = {
adminPresentUserInvitations: {name: 'adminPresentUserInvitations', enable: true},
adminRemoveUserHnrWarning: {name: 'adminRemoveUserHnrWarning', enable: true},
adminCreateUserMakerGroup: {name: 'adminCreateUserMakerGroup', enable: true},
adminAddUserMedal: {name: 'adminAddUserMedal', enable: true},
adminRemoveUserMedal: {name: 'adminRemoveUserMedal', enable: true},
adminUserDelete: {name: 'adminUserDelete', enable: true},
adminUserEdit: {name: 'adminUserEdit', enable: true},
@@ -768,6 +892,8 @@ module.exports = {
adminPresentUserInvitations: {name: 'adminPresentUserInvitations', content: 'ADMIN_PRESENT_USER_INVITATIONS', enable: true},
adminRemoveUserHnrWarning: {name: 'adminRemoveUserHnrWarning', content: 'ADMIN_REMOVE_USER_HNR_WARNING', enable: true},
adminCreateUserMakerGroup: {name: 'adminCreateUserMakerGroup', content: 'ADMIN_CREATE_USER_MAKER_GROUP', enable: true},
adminAddUserMedal: {name: 'adminAddUserMedal', content: 'ADMIN_ADD_USER_MEDAL', enable: true},
adminRemoveUserMedal: {name: 'adminRemoveUserMedal', content: 'ADMIN_REMOVE_USER_MEDAL', enable: true},
adminBanUserInviter: {name: 'adminBanUserInviter', content: 'ADMIN_BAN_USER_INVITER', enable: true}
}
},
@@ -1426,34 +1552,35 @@ module.exports = {
* items number in per list page settings
* NOTE: you can change these value at anytime if you understand it
*
* @topicsPerPage: forum topic list page settings
* @repliesPerPage: forum topic replies list page settings
* @topicsSearchPerPage: forum topic search list page settings
* @torrentsPerPage: torrents list page settings
* @torrentsCommentsPerPage: torrent comments list settings
* @makeGroupTorrentsPerPage: torrent of make group list page settings
* @albumTorrentsPerPage: torrent of album list page settings
* @tracesPerPage: system traces log list page settings
* @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
* @topicsPerPage: forum topic list page settings
* @repliesPerPage: forum topic replies list page settings
* @topicsSearchPerPage: forum topic search list page settings
* @torrentsPerPage: torrents list page settings
* @torrentsCommentsPerPage: torrent comments list settings
* @makeGroupTorrentsPerPage: torrent of make group list page settings
* @albumTorrentsPerPage: torrent of album list page settings
* @tracesPerPage: system traces log list page settings
* @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
* @officialInvitationsListPerPage: official invitations list page settings
* @userInvitationsListPerPage: users invitations list page settings
* @userDataLogsListPerPage: users data history logs list page settings
* @medalUsersListPerPage: medal owned users list page settings
*
* @uploaderUserListPerPage: admin management uploader access list page settings
* @messageBoxListPerPage: message box list page settings
* @followListPerPage: users follow list page settings
* @uploaderUserListPerPage: admin management uploader access list page settings
* @messageBoxListPerPage: message box list page settings
* @followListPerPage: users follow list page settings
*
* @requestListPerPage: request list page settings
* @requestCommentsPerPage: request comments list settings
* @requestListPerPage: request list page settings
* @requestCommentsPerPage: request comments list settings
*
* @homeOrderTorrentListPerType: every type of torrent showed in home settings
* @homeNewestTorrentListPerType: every type of torrent of newest showed in home settings
* @homeHelpListLimit: help items number of home settings
* @homeNoticeListLimit: notice items number of home settings
* @homeNewTopicListLimit: new topic items number of home settings
* @homeHelpListLimit: help items number of home settings
* @homeNoticeListLimit: notice items number of home settings
* @homeNewTopicListLimit: new topic items number of home settings
* @homeNewestTorrentsListLimit: newest torrents items number of home settings
*
* @examinationUserListPerPage: users item number of examination result page
@@ -1478,6 +1605,7 @@ module.exports = {
officialInvitationsListPerPage: 20,
userInvitationsListPerPage: 10,
userDataLogsListPerPage: 20,
medalUsersListPerPage: 60,
uploaderUserListPerPage: 20,
messageBoxListPerPage: 10,

View File

@@ -13,7 +13,7 @@
state: 'about',
type: 'dropdown',
roles: ['*'],
position: 7
position: 19
});
menuService.addSubMenuItem('topbar', 'about', {

View File

@@ -531,10 +531,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(m.desc);
e.$options.hideable = true;

View File

@@ -25,13 +25,13 @@
</thead>
<tbody>
<tr ng-repeat="b in vm.blackListConfig">
<td class="col-md-1 td-v-middle width-50">
<td class="col-md-1 td-v-middle min-width-50">
{{$index}}
</td>
<td class="col-md-3 td-v-middle width-150">
<td class="col-md-3 td-v-middle min-width-150">
<strong>{{b.name}}</strong>
</td>
<td class="col-md-8 td-v-middle width-300">
<td class="col-md-8 td-v-middle min-width-300">
{{b.reason | translate}}
</td>
</tr>

View File

@@ -64,7 +64,7 @@
<div class="row margin-bottom-20">
<div class="col-sm-12">
<div class="maker-button text-right">
<button class="btn btn-width-120 margin-top-5" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
<button class="btn btn-min-width-120 margin-top-5" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
ng-if="vm.user.isOper || vm.isOwner(vm.maker)"
uib-popover-template="vm.addMemberPopover.templateUrl"
popover-append-to-body="true"
@@ -76,11 +76,11 @@
ng-click="vm.addMemberPopover.isOpen=true; vm.addMemberPopover.username='';">
{{'ABOUT.BTN_ADD_USER' | translate}}
</button>
<button class="btn btn-width-120 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-120 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper || vm.isOwner(vm.maker)" ng-click="vm.beginEditMakerDesc(vm.maker)">
{{'ABOUT.BTN_EDIT_DESC' | translate}}
</button>
<div class="btn-group width-120 margin-top-5" ng-if="vm.user.isAdmin" uib-dropdown dropdown-append-to-body>
<div class="btn-group min-width-120 margin-top-5" ng-if="vm.user.isAdmin" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button"
class="btn btn-block"
mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
@@ -100,7 +100,7 @@
</li>
</ul>
</div>
<button class="btn btn-width-120 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-120 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isAdmin" ng-click="vm.beginRemoveMakerGroup(vm.maker)">
{{'ABOUT.BTN_REMOVE_GROUP' | translate}}
</button>
@@ -338,7 +338,7 @@
placeholder="{{ 'STATUS_FIELD.USERNAME' | translate }}" autofocus>
</div>
<div class="margin-top-10">
<button class="btn btn-default btn-width-80" ng-disabled="!vm.addMemberPopover.username"
<button class="btn btn-default btn-min-width-80" ng-disabled="!vm.addMemberPopover.username"
ng-click="vm.addMember();">{{ 'FORUMS.BTN_ADD' | translate }}
</button>
</div>

View File

@@ -212,10 +212,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(c.overview);
e.$options.hideable = true;

View File

@@ -29,16 +29,16 @@
<div class="row">
<div class="col-sm-12">
<div class="album-button text-right">
<button class="btn btn-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper" ng-click="vm.beginEditAlbumOverview(vm.album)">
{{'ALBUMS.BTN_EDIT_OVERVIEW' | translate}}
</button>
<button class="btn btn-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper" ng-click="vm.beginRemoveAlbum(vm.album)">
{{'ALBUMS.BTN_REMOVE_ALBUM' | translate}}
</button>
<div class="btn-group width-160 margin-top-5" ng-if="vm.user.isOper" uib-dropdown dropdown-append-to-body>
<div class="btn-group min-width-160 margin-top-5" ng-if="vm.user.isOper" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button"
class="btn btn-block"
mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
@@ -56,7 +56,7 @@
</ul>
</div>
<button class="btn btn-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper" ng-click="vm.beginToggleHomeStatus(vm.album)">
{{(vm.album.isHomeStatus ? 'ALBUMS.BTN_PULL_FROM_HOME' : 'ALBUMS.BTN_PUSH_INFO_HOME') | translate}}
</button>

View File

@@ -48,7 +48,7 @@
next-text="{{ 'PAGE_TEXT_NEXT' | translate}}" last-text="{{ 'PAGE_TEXT_LAST' | translate}}">
</ul>
<div class="pull-right margin-top-20 margin-bottom-30">
<button class="btn btn-success btn-width-100" ng-click="vm.deleteSelected()">{{ 'BUTTON_MESSAGE_DELETE' | translate }}
<button class="btn btn-success btn-min-width-100" ng-click="vm.deleteSelected()">{{ 'BUTTON_MESSAGE_DELETE' | translate }}
</button>
</div>
</div>

View File

@@ -13,8 +13,20 @@
title: 'MENU_CHAT',
state: 'chat',
roles: ['*'],
class: 'sm-hide',
target: '_blank',
position: 6
position: 7
});
//add to more
menuService.addSubMenuItem('topbar', 'more', {
title: 'MENU_CHAT',
state: 'chat',
roles: ['*'],
faIcon: 'fa-comment-alt-dots',
faClass: 'text-mt',
target: '_blank',
position: 2
});
}
}());

View File

@@ -172,10 +172,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(c.overview);
e.$options.hideable = true;

View File

@@ -41,16 +41,16 @@
<div class="row">
<div class="col-sm-12">
<div class="collection-button text-right">
<button class="btn btn-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper" ng-click="vm.beginEditCollectionOverview(vm.collection)">
{{'COLLECTIONS.BTN_EDIT_OVERVIEW' | translate}}
</button>
<button class="btn btn-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
<button class="btn btn-min-width-160 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.user.isOper" ng-click="vm.beginRemoveCollection(vm.collection)">
{{'COLLECTIONS.BTN_REMOVE_COLLECTION' | translate}}
</button>
<div class="btn-group width-160 margin-top-5" ng-if="vm.user.isOper" uib-dropdown dropdown-append-to-body>
<div class="btn-group min-width-160 margin-top-5" ng-if="vm.user.isOper" uib-dropdown dropdown-append-to-body>
<button id="btn-append-to-body" type="button"
class="btn btn-block"
mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
@@ -67,7 +67,7 @@
</li>
</ul>
</div>
<span class="width-160 sm-hide md-hide lg-hide" style="display: inline-block">&nbsp;</span>
<span class="min-width-160 sm-hide md-hide lg-hide" style="display: inline-block">&nbsp;</span>
</div>
</div>
</div>

View File

@@ -65,7 +65,6 @@ exports.collectioninfo = function (req, res) {
});
};
/**
* Create an collection
*/

View File

@@ -50,7 +50,9 @@
MENU_ADMIN_TICKETS: 'Support Services Center',
MENU_USERS_ADMIN: 'Manage Users',
MENU_UPLOAD: 'Upload',
MENU_MEDALS: 'Medals',
MENU_FORUMS: 'Forums',
MENU_MORE: 'More',
MENU_REQUESTS: 'Requests',
MENU_ABOUT: 'About',
MENU_ABOUT_MANUAL: 'User Manual',
@@ -90,6 +92,7 @@
MENU_MY_INVITE: 'My Invitations',
MENU_MY_DATA_CENTER: 'Data center',
MENU_ACCOUNT_STATUS: 'Account Status',
MENU_TORRENTS_STATUS: 'Torrents Status',
EDIT_PROFILE: 'Edit Profile',
EDIT_PROFILE_PIC: 'Edit Profile Picture',
EDIT_SIGNATURE: 'Edit Signature Of Forum',
@@ -250,6 +253,7 @@
VIP: 'Vip',
VIP_DONATE: 'Vip Donate',
VIP_RULES: 'Vip Rules',
MEDALS: 'Medals Wall',
FORUM: 'Forum',
REQUESTS: 'Requests',
REQUESTS_MY: 'My Requests',
@@ -278,6 +282,7 @@
MESSAGES_BOX: 'Message Box',
MESSAGES_SEND: 'Send Message',
STATUS_ACCOUNT: 'Account Status',
STATUS_TORRENTS: 'Torrents Status',
STATUS_UPLOADED: 'Uploaded',
STATUS_SEEDING: 'Seeding',
STATUS_LEECHING: 'Leeching',
@@ -876,6 +881,7 @@
BUTTON_SELECT_PICTURE: 'Select Picture',
BUTTON_USE_THIS_PICTURE: 'Use This Picture',
BUTTON_CANCEL: 'Cancel',
BUTTON_CLOSE: 'Close',
BUTTON_SAVE: 'Save',
BUTTON_SET: 'Set',
BUTTON_OK: 'Ok',
@@ -975,7 +981,7 @@
},
//user status
STATUS_ACCOUNT: 'Account Status',
STATUS_ACCOUNT: 'My Account Status',
STATUS_UPLOADED: 'Uploaded torrents',
STATUS_SEEDING: 'Seeding torrents',
STATUS_DOWNLOADING: 'Downloading torrents',
@@ -1004,6 +1010,7 @@
BTN_VIEW_USER_DATA_CENTER: 'Data Center',
BTN_EDIT: 'Edit',
BTN_REMOVE: 'Remove',
BTN_ADD_MEDAL: 'Add Medal',
PICTURE: 'Profile picture',
RESET_DEFAULT_PICTURE: 'Reset to default picture',
ADD_VIP_MONTHS: '+ VIP a month',
@@ -1227,6 +1234,8 @@
USER_UPLOADED_FLAG: '{{name}} uploaded',
USER_DOWNLOADED_FLAG: '{{name}} downloaded',
USER_SCORE_LEVEL: '{{name}} score level',
USER_RATIO_FLAG: '{{name}} ratio',
USER_MEDAL_FLAG: '{{name}} medal',
//traces
ADMIN_TRACES_LIST: 'Traces List',
@@ -1472,6 +1481,115 @@
}
},
// medals wall
MEDALS: {
MEDALS_TITLE: 'Medals Wall',
TYPES_COUNT: 'Medals type count',
MEDALS_OPENED_COUNT: 'Medals opened count',
MEDALS_AWARD_COUNT: 'Medals award count',
SELECT_MEDAL_TO_USER: 'Please select a medal transfer to user - {{uname}}',
ADD_SUCCESSFULLY: 'Add medal to user successfully',
ADD_FAILED: 'Add medal to user failed',
REMOVE_SUCCESSFULLY: 'Remove medal to user successfully',
REMOVE_FAILED: 'Remove medal to user failed',
MEDALS_OVERVIEW: 'The medal is the identity of the users identity and contribution to the site. The medal is awarded in three ways: system automatic help, administrator help, and user self help. The self help medal requires the user to self-request according to the corresponding conditions. Different medals have different system treatments, and the site will also hold a variety of events for users of different medal groups from time to time.',
CMD_LIST_USER: 'List users',
CMD_REQUEST: 'Request',
HELP_CONDITION: 'Condition',
OWNED_USERS: 'Owned users',
USERS_IS_LOADING: 'Loading uses, please wait ...',
USERS_IS_EMPTY: 'Has no anybody owned this medal',
REQUEST_CONFIRM_CANCEL: 'Cancel',
REQUEST_CONFIRM_OK: 'OK',
REQUEST_CONFIRM_HEADER_TEXT: 'Request medal',
REQUEST_CONFIRM_BODY_TEXT: 'Are you sure want to request this medal with score {{score}} ?',
REQUEST_SUCCESSFULLY: 'Request medal successfully',
REQUEST_ERROR: 'Request medal failed',
AWARD_AT: 'Award at',
CATS: {
WORKERS: 'Workers medals',
USERS: 'Users medals',
VIP: 'VIP medals',
EVENTS: 'Events medals',
COMMEMORATIVE: 'Commemorative Medals'
},
PASSHELP: {
SYS: 'System automatic help',
ADMIN: 'Administrator help',
SELF: 'User self help'
},
DESC: {
ROOT: 'Root Administrator Medal',
NETWORK_ADMIN: 'Network Administrator Medal',
SUPPORT_ADMIN: 'Support Administrator Medal',
FORUM_ADMIN: 'Forums Administrator Medal',
RESOURCE_ADMIN: 'Resources Administrator Medal',
AMBASSADOR: 'Site Ambassador Medal',
FORUM_MODERATORS: 'Forum Moderators Medal',
MAKER_FOUNDER: 'Resource Group Founder Medal',
UPLOADER: 'Resource Uploader Medal',
RETIREE: 'Site Retiree Medal',
BEAUTY_3000: 'Beauty Children User Medal',
ROAM: 'Roaming Safe User Medal',
NO_EXAMINATION: 'No Examination User Medal',
SLUGGER: 'Site Slugger User Medal',
ELDER: 'Site Elder User Medal',
FOREVER_VIP: 'Forever VIP Medal',
YEARLY_VIP: 'Yearly VIP Medal',
MONTHLY_VIP: 'Monthly VIP Medal',
GUEST_VIP: 'Guest VIP Medal',
SITE_BEGIN: 'Site Begin Medal',
FOR_ONE_YEARS: 'Site One Year Medal',
FOR_TWO_YEARS: 'Site Two Years Medal',
EVENT_NAME: 'Special Event Medal'
},
FOOTERSTRING: {
ROOT: 'ROOT',
NETWORK_ADMIN: 'NA',
SUPPORT_ADMIN: 'SA',
FORUM_ADMIN: 'FA',
RESOURCE_ADMIN: 'RA',
AMBASSADOR: 'AMB',
FORUM_MODERATORS: 'FM',
MAKER_FOUNDER: 'MGF',
UPLOADER: 'UPER',
RETIREE: 'RET',
BEAUTY_3000: 'BEAUTY',
ROAM: 'ROAM',
NO_EXAMINATION: 'NOEXAM',
SLUGGER: 'SLUGGER',
ELDER: 'ELDER',
FOREVER_VIP: 'VIP',
YEARLY_VIP: 'VIP',
MONTHLY_VIP: 'VIP',
GUEST_VIP: 'VIP',
SITE_BEGIN: 'YEARS',
FOR_ONE_YEARS: 'YEARS',
FOR_TWO_YEARS: 'YEARS',
EVENT_NAME: '2018'
},
HEADERSTRING: {
FOREVER_VIP: 'F',
YEARLY_VIP: 'Y',
MONTHLY_VIP: 'M',
GUEST_VIP: 'G',
SITE_BEGIN: '0',
FOR_ONE_YEARS: '1',
FOR_TWO_YEARS: '2',
EVENT_NAME: 'EVE'
}
},
// data center
DATA_CENTER: {
ITEM_SCORE: 'Score data analysis',
@@ -1518,6 +1636,7 @@
REQUEST_ACCEPT_TO: 'Your response of request was accepted <a href=/requests/{{rid}}>{{rid}}</a>',
SCORE_EXCHANGE_INVITATION: 'Exchange an invitation',
SCORETO_REMOVE_WARNING: 'Remove a H&R warning <a href=/torrents/{{tid}}>{{tid}}</a>',
SCORETO_REQUEST_MEDAL: 'Request medal: {{medalDesc | translate}}',
ACTIVE_IDLE_ACCOUNT: 'Active account idle status',
DAILY_CHECK_IN: 'Daily check in',
SEED_TIMED: 'Torrent seeding timed increased score <a href=/torrents/{{tid}}>{{tid}}</a>',
@@ -1531,7 +1650,7 @@
BAD_REQUEST: 'Bad Request',
FORBIDDEN: 'Forbidden',
MADE_BAD_REQUEST: 'You made a bad request',
NOT_AUTHORIZED_THIS: 'You are not authorized to access this resource',
NOT_AUTHORIZED_THIS: 'You are not authorized to access this resource, if your session or cookie is expired, please <a href="/authentication/signin">sign in</a>.',
NOT_FOUND: 'Not Found',
PAGE_NOT_FOUND: 'Page Or Resources Not Found',
ACCESS_DENY: 'Your current IP is restricted to access this resourceFor more help, please contact our {{sNameDesc | translate}} by <strong><a href="/messages/send?to={{sName}}">Message</a></strong> or <strong><a href="mailto:{{sMail}}">Email</a></strong>.'
@@ -1833,6 +1952,8 @@
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}}`',
ADMIN_CREATE_USER_MAKER_GROUP: '`{{by.displayName}}` create user maker group: `-={{name}}=-`',
ADMIN_ADD_USER_MEDAL: '`{{by.displayName}}` add user medal: `{{medalName}}`',
ADMIN_REMOVE_USER_MEDAL: '`{{by.displayName}}` remove user medal: `{{medalName}}`',
ADMIN_BAN_USER_INVITER: '`{{by.displayName}}` update account status to: `{{status}}`, reason: invited user [{{uname}}] was banned because [{{reason | translate}}]'
},
@@ -1875,7 +1996,9 @@
UPLOAD_ACCESS_DENY: 'System only accepts resources group to upload torrents',
READ_TORRENT_FILE_FAILD: 'The torrent file parsing error. Please check your torrent file to check if some of the necessary information is missing',
MOVE_TORRENT_FILE_ERROR: 'The torrent file was moved incorrectly. Please do not repeat the submit operation quickly or the uploaded torrent file is missing.',
YOU_ALREADY_CHECK_IN: 'You already checked in today'
YOU_ALREADY_CHECK_IN: 'You already checked in today',
USER_ALREADY_HAS_THIS_MEDAL: 'This user already has this medal',
USER_HAS_NOT_THIS_MEDAL: 'This user has not this medal'
},
//server message string, content string support markdown and emoji

View File

@@ -50,7 +50,9 @@
MENU_ADMIN_TICKETS: '客戶服務中心',
MENU_USERS_ADMIN: '用戶管理',
MENU_UPLOAD: '發布',
MENU_MEDALS: '勳章',
MENU_FORUMS: '論壇',
MENU_MORE: '更多',
MENU_REQUESTS: '求種',
MENU_ABOUT: '關於',
MENU_ABOUT_MANUAL: '用戶手冊',
@@ -90,6 +92,7 @@
MENU_MY_INVITE: '我的邀請',
MENU_MY_DATA_CENTER: '數據中心',
MENU_ACCOUNT_STATUS: '帳戶狀態',
MENU_TORRENTS_STATUS: '種子狀態',
EDIT_PROFILE: '修改個人資訊',
EDIT_PROFILE_PIC: '修改個人頭像',
EDIT_SIGNATURE: '修改論壇簽名',
@@ -250,6 +253,7 @@
VIP: 'Vip',
VIP_DONATE: '捐贈VIP',
VIP_RULES: 'Vip用戶協議',
MEDALS: '勳章牆',
FORUM: '論壇',
REQUESTS: '求種',
REQUESTS_MY: '我的求種',
@@ -278,6 +282,7 @@
MESSAGES_BOX: '站內訊息',
MESSAGES_SEND: '傳送訊息',
STATUS_ACCOUNT: '帳戶狀態',
STATUS_TORRENTS: '種子狀態',
STATUS_UPLOADED: '我的種子',
STATUS_SEEDING: '正在做種',
STATUS_LEECHING: '正在下載',
@@ -876,6 +881,7 @@
BUTTON_SELECT_PICTURE: '選擇圖片',
BUTTON_USE_THIS_PICTURE: '應用圖片',
BUTTON_CANCEL: '取消',
BUTTON_CLOSE: '關閉',
BUTTON_SAVE: '儲存',
BUTTON_SET: '設定',
BUTTON_OK: '確定',
@@ -975,7 +981,7 @@
},
//user status
STATUS_ACCOUNT: '帳戶狀態',
STATUS_ACCOUNT: '我的帳戶狀態',
STATUS_UPLOADED: '我上傳的種子',
STATUS_SEEDING: '正在做種的種子',
STATUS_DOWNLOADING: '正在下載的種子',
@@ -1004,6 +1010,7 @@
BTN_VIEW_USER_DATA_CENTER: '數據中心',
BTN_EDIT: '編輯',
BTN_REMOVE: '刪除',
BTN_ADD_MEDAL: '頒發勳章',
PICTURE: '頭像',
RESET_DEFAULT_PICTURE: '重置為預設圖片',
ADD_VIP_MONTHS: '+ VIP一個月',
@@ -1227,6 +1234,8 @@
USER_UPLOADED_FLAG: '{{name}} 的上傳量',
USER_DOWNLOADED_FLAG: '{{name}} 的下載量',
USER_SCORE_LEVEL: '{{name}} 的積分等級',
USER_RATIO_FLAG: '{{name}} 的分享率',
USER_MEDAL_FLAG: '{{name}} 的勳章總數',
//traces
ADMIN_TRACES_LIST: '系統日誌',
@@ -1472,6 +1481,115 @@
}
},
// medals wall
MEDALS: {
MEDALS_TITLE: '勳章牆',
TYPES_COUNT: '勳章類型',
MEDALS_OPENED_COUNT: '勳章開放數',
MEDALS_AWARD_COUNT: '勳章頒發數',
SELECT_MEDAL_TO_USER: '請選擇要頒發的勳章 - {{uname}}',
ADD_SUCCESSFULLY: '給用戶添加勳章成功',
ADD_FAILED: '給用戶添加勳章失敗',
REMOVE_SUCCESSFULLY: '移除用戶勳章成功',
REMOVE_FAILED: '移除用戶勳章失敗',
MEDALS_OVERVIEW: '勳章是用戶身份及為站點所做的貢獻的標識,勳章頒發分為系統自動頒發、管理員幫助頒發與用戶自助頒發三種,自助頒發的勳章需要用戶自已根據相應的條件自助申領。不同的勳章對應有不同的系統待遇,站點也會不定期的針對不同的勳章群體用戶舉辦豐富多樣的活動,敬請大家期待。',
CMD_LIST_USER: '查看用戶',
CMD_REQUEST: '申請勳章',
HELP_CONDITION: '申請條件',
OWNED_USERS: '擁有用戶',
USERS_IS_LOADING: '正在裝載用戶列表,請稍候...',
USERS_IS_EMPTY: '還沒有任何用戶擁有此勳章',
REQUEST_CONFIRM_CANCEL: '取消',
REQUEST_CONFIRM_OK: '確定',
REQUEST_CONFIRM_HEADER_TEXT: '申請勳章',
REQUEST_CONFIRM_BODY_TEXT: '您確定要使用 {{score}} 積分來申請這枚勳章嗎?',
REQUEST_SUCCESSFULLY: '勳章申請成功',
REQUEST_ERROR: '勳章申請失敗',
AWARD_AT: '授於',
CATS: {
WORKERS: '工作人員類勳章',
USERS: '用戶類勳章',
VIP: 'VIP 類勳章',
EVENTS: '特別事件類勳章',
COMMEMORATIVE: '站點紀念類勳章'
},
PASSHELP: {
SYS: '系統自動頒發',
ADMIN: '管理員頒發',
SELF: '用戶自助申請'
},
DESC: {
ROOT: '系統管理員勳章',
NETWORK_ADMIN: '網站管理員勳章',
SUPPORT_ADMIN: '客戶服務管理員勳章',
FORUM_ADMIN: '論壇管理員勳章',
RESOURCE_ADMIN: '資源管理員勳章',
AMBASSADOR: '網站外交大使勳章',
FORUM_MODERATORS: '論壇版主勳章',
MAKER_FOUNDER: '資源發布組組長勳章',
UPLOADER: '資源發布專員勳章',
RETIREE: '網站退休工作人員勳章',
BEAUTY_3000: '佳麗三千后宮勳章',
ROAM: '雲遊四方保號勳章',
NO_EXAMINATION: '網站免考用戶勳章',
SLUGGER: '網站種子用戶勳章',
ELDER: '網站元老用戶勳章',
FOREVER_VIP: '終身 VIP 勳章',
YEARLY_VIP: '年度 VIP 勳章',
MONTHLY_VIP: '月度 VIP 勳章',
GUEST_VIP: '來賓 VIP 勳章',
SITE_BEGIN: '網站開張紀念勳章',
FOR_ONE_YEARS: '網站1週年紀念勳章',
FOR_TWO_YEARS: '網站2週年紀念勳章',
EVENT_NAME: '特別活動勳章'
},
FOOTERSTRING: {
ROOT: '站長',
NETWORK_ADMIN: '站長',
SUPPORT_ADMIN: '客服',
FORUM_ADMIN: '論壇',
RESOURCE_ADMIN: '資源',
AMBASSADOR: '使臣',
FORUM_MODERATORS: '版主',
MAKER_FOUNDER: '組長',
UPLOADER: '發布',
RETIREE: '退休',
BEAUTY_3000: '佳麗',
ROAM: '雲遊',
NO_EXAMINATION: '免考',
SLUGGER: '種子',
ELDER: '元老',
FOREVER_VIP: 'VIP',
YEARLY_VIP: 'VIP',
MONTHLY_VIP: 'VIP',
GUEST_VIP: 'VIP',
SITE_BEGIN: '週年',
FOR_ONE_YEARS: '週年',
FOR_TWO_YEARS: '週年',
EVENT_NAME: '2018'
},
HEADERSTRING: {
FOREVER_VIP: '終',
YEARLY_VIP: '年',
MONTHLY_VIP: '月',
GUEST_VIP: '賓',
SITE_BEGIN: '0',
FOR_ONE_YEARS: '1',
FOR_TWO_YEARS: '2',
EVENT_NAME: '活動'
}
},
// data center
DATA_CENTER: {
ITEM_SCORE: '積分數據分析',
@@ -1518,6 +1636,7 @@
REQUEST_ACCEPT_TO: '您的響應被求種請求者接受 <a href=/requests/{{rid}}>{{rid}}</a>',
SCORE_EXCHANGE_INVITATION: '兌換了一張邀請函',
SCORETO_REMOVE_WARNING: '移除了一個 H&R 警告 <a href=/torrents/{{tid}}>{{tid}}</a>',
SCORETO_REQUEST_MEDAL: '申請勳章: {{medalDesc | translate}}',
ACTIVE_IDLE_ACCOUNT: '重新激活帳戶狀態',
DAILY_CHECK_IN: '每日簽到',
SEED_TIMED: '做種時間獲得的積分 <a href=/torrents/{{tid}}>{{tid}}</a>',
@@ -1531,7 +1650,7 @@
BAD_REQUEST: '請求錯誤',
FORBIDDEN: '請求禁止',
MADE_BAD_REQUEST: '您發起了一個無效的請求',
NOT_AUTHORIZED_THIS: '您無權訪問此資源',
NOT_AUTHORIZED_THIS: '您無權訪問此資源,如果您的 session 或 cookie 已過期,請 <a href="/authentication/signin">重新登錄</a>。',
NOT_FOUND: '無法訪問',
PAGE_NOT_FOUND: '沒有找到頁面或資源',
ACCESS_DENY: '您的當前IP被限制訪問此資源如需幫助請給{{sNameDesc | translate}}傳送 <strong><a href="/messages/send?to={{sName}}">訊息</a></strong> 或 <strong><a href="mailto:{{sMail}}">郵件</a></strong>.'
@@ -1833,6 +1952,8 @@
ADMIN_PRESENT_USER_INVITATIONS: '`{{by.displayName}}` 贈送 `{{numbers}}` 個官方邀請函, 有效期 `{{days}}` 天',
ADMIN_REMOVE_USER_HNR_WARNING: '`{{by.displayName}}` 移除 H&R 警告, complete id: `{{complete}}`',
ADMIN_CREATE_USER_MAKER_GROUP: '`{{by.displayName}}` 創建用戶資源小組: `-={{name}}=-`',
ADMIN_ADD_USER_MEDAL: '`{{by.displayName}}` 添加用戶勳章: `{{medalName}}`',
ADMIN_REMOVE_USER_MEDAL: '`{{by.displayName}}` 移除用戶勳章: `{{medalName}}`',
ADMIN_BAN_USER_INVITER: '`{{by.displayName}}` 改變帳戶狀態為: `{{status}}`, 理由: 邀請的用戶[{{uname}}]因為[{{reason | translate}}]被禁止'
},
@@ -1875,7 +1996,9 @@
UPLOAD_ACCESS_DENY: '當前系統只接受資源製作小組上傳種子',
READ_TORRENT_FILE_FAILD: '種子檔案解析錯誤,請檢查您的種子檔案,看是否缺少某些必要資訊',
MOVE_TORRENT_FILE_ERROR: '種子檔案移動錯誤,請不要快速重複進行提交操作或者上傳的種子檔案已丟失',
YOU_ALREADY_CHECK_IN: '您今天已經完成簽到了,不能重復簽到喔!'
YOU_ALREADY_CHECK_IN: '您今天已經完成簽到了,不能重復簽到喔!',
USER_ALREADY_HAS_THIS_MEDAL: '該用戶已經擁有了這枚勳章',
USER_HAS_NOT_THIS_MEDAL: '該用戶還沒有這枚勳章'
},
//server message string, content string support markdown and emoji

View File

@@ -50,7 +50,9 @@
MENU_ADMIN_TICKETS: '客户服务中心',
MENU_USERS_ADMIN: '用户管理',
MENU_UPLOAD: '发布',
MENU_MEDALS: '勋章',
MENU_FORUMS: '论坛',
MENU_MORE: '更多',
MENU_REQUESTS: '求种',
MENU_ABOUT: '关于',
MENU_ABOUT_MANUAL: '用户手册',
@@ -90,6 +92,7 @@
MENU_MY_INVITE: '我的邀请',
MENU_MY_DATA_CENTER: '数据中心',
MENU_ACCOUNT_STATUS: '帐户状态',
MENU_TORRENTS_STATUS: '种子状态',
EDIT_PROFILE: '修改个人信息',
EDIT_PROFILE_PIC: '修改个人头像',
EDIT_SIGNATURE: '修改论坛签名',
@@ -250,6 +253,7 @@
VIP: 'Vip',
VIP_DONATE: '捐赠VIP',
VIP_RULES: 'Vip用户协议',
MEDALS: '勋章墙',
FORUM: '论坛',
REQUESTS: '求种',
REQUESTS_MY: '我的求种',
@@ -278,6 +282,7 @@
MESSAGES_BOX: '站内消息',
MESSAGES_SEND: '发送消息',
STATUS_ACCOUNT: '帐户状态',
STATUS_TORRENTS: '种子状态',
STATUS_UPLOADED: '我的种子',
STATUS_SEEDING: '正在做种',
STATUS_LEECHING: '正在下载',
@@ -876,6 +881,7 @@
BUTTON_SELECT_PICTURE: '选择图片',
BUTTON_USE_THIS_PICTURE: '应用图片',
BUTTON_CANCEL: '取消',
BUTTON_CLOSE: '关闭',
BUTTON_SAVE: '保存',
BUTTON_SET: '设置',
BUTTON_OK: '确定',
@@ -975,7 +981,7 @@
},
//user status
STATUS_ACCOUNT: '帐户状态',
STATUS_ACCOUNT: '我的帐户状态',
STATUS_UPLOADED: '我上传的种子',
STATUS_SEEDING: '正在做种的种子',
STATUS_DOWNLOADING: '正在下载的种子',
@@ -1004,6 +1010,7 @@
BTN_VIEW_USER_DATA_CENTER: '数据中心',
BTN_EDIT: '编辑',
BTN_REMOVE: '删除',
BTN_ADD_MEDAL: '颁发勋章',
PICTURE: '头像',
RESET_DEFAULT_PICTURE: '重置为默认图片',
ADD_VIP_MONTHS: '+ VIP一个月',
@@ -1227,6 +1234,8 @@
USER_UPLOADED_FLAG: '{{name}} 的上传量',
USER_DOWNLOADED_FLAG: '{{name}} 的下载量',
USER_SCORE_LEVEL: '{{name}} 的积分等级',
USER_RATIO_FLAG: '{{name}} 的分享率',
USER_MEDAL_FLAG: '{{name}} 的勋章总数',
//traces
ADMIN_TRACES_LIST: '系统日志',
@@ -1472,6 +1481,115 @@
}
},
// medals wall
MEDALS: {
MEDALS_TITLE: '勋章墙',
TYPES_COUNT: '勋章类型',
MEDALS_OPENED_COUNT: '勋章开放数',
MEDALS_AWARD_COUNT: '勋章颁发数',
SELECT_MEDAL_TO_USER: '请选择要颁发的勋章 - {{uname}}',
ADD_SUCCESSFULLY: '给用户添加勋章成功',
ADD_FAILED: '给用户添加勋章失败',
REMOVE_SUCCESSFULLY: '移除用户勋章成功',
REMOVE_FAILED: '移除用户勋章失败',
MEDALS_OVERVIEW: '勋章是用户身份及为站点所做的贡献的标识,勋章颁发分为系统自动颁发、管理员帮助颁发与用户自助颁发三种,自助颁发的勋章需要用户自已根据相应的条件自助申领。不同的勋章对应有不同的系统待遇,站点也会不定期的针对不同的勋章群体用户举办丰富多样的活动,敬请大家期待。',
CMD_LIST_USER: '查看用户',
CMD_REQUEST: '申请勋章',
HELP_CONDITION: '申请条件',
OWNED_USERS: '拥有用户',
USERS_IS_LOADING: '正在装载用户列表,请稍候...',
USERS_IS_EMPTY: '还没有任何用户拥有此勋章',
REQUEST_CONFIRM_CANCEL: '取消',
REQUEST_CONFIRM_OK: '确定',
REQUEST_CONFIRM_HEADER_TEXT: '申请勋章',
REQUEST_CONFIRM_BODY_TEXT: '您确定要使用 {{score}} 积分来申请这枚勋章吗?',
REQUEST_SUCCESSFULLY: '勋章申请成功',
REQUEST_ERROR: '勋章申请失败',
AWARD_AT: '授于',
CATS: {
WORKERS: '工作人员类勋章',
USERS: '用户类勋章',
VIP: 'VIP 类勋章',
EVENTS: '特别事件类勋章',
COMMEMORATIVE: '站点纪念类勋章'
},
PASSHELP: {
SYS: '系统自动颁发',
ADMIN: '管理员颁发',
SELF: '用户自助申请'
},
DESC: {
ROOT: '系统管理员勋章',
NETWORK_ADMIN: '网站管理员勋章',
SUPPORT_ADMIN: '客户服务管理员勋章',
FORUM_ADMIN: '论坛管理员勋章',
RESOURCE_ADMIN: '资源管理员勋章',
AMBASSADOR: '网站外交大使勋章',
FORUM_MODERATORS: '论坛版主勋章',
MAKER_FOUNDER: '资源发布组组长勋章',
UPLOADER: '资源发布专员勋章',
RETIREE: '网站退休工作人员勋章',
BEAUTY_3000: '佳丽三千后宫勋章',
ROAM: '云游四方保号勋章',
NO_EXAMINATION: '网站免考用户勋章',
SLUGGER: '网站种子用户勋章',
ELDER: '网站元老用户勋章',
FOREVER_VIP: '终身 VIP 勋章',
YEARLY_VIP: '年度 VIP 勋章',
MONTHLY_VIP: '月度 VIP 勋章',
GUEST_VIP: '来宾 VIP 勋章',
SITE_BEGIN: '网站开张纪念勋章',
FOR_ONE_YEARS: '网站1周年纪念勋章',
FOR_TWO_YEARS: '网站2周年纪念勋章',
EVENT_NAME: '特别活动勋章'
},
FOOTERSTRING: {
ROOT: '站长',
NETWORK_ADMIN: '站长',
SUPPORT_ADMIN: '客服',
FORUM_ADMIN: '论坛',
RESOURCE_ADMIN: '资源',
AMBASSADOR: '使臣',
FORUM_MODERATORS: '版主',
MAKER_FOUNDER: '组长',
UPLOADER: '发布',
RETIREE: '退休',
BEAUTY_3000: '佳丽',
ROAM: '云游',
NO_EXAMINATION: '免考',
SLUGGER: '种子',
ELDER: '元老',
FOREVER_VIP: 'VIP',
YEARLY_VIP: 'VIP',
MONTHLY_VIP: 'VIP',
GUEST_VIP: 'VIP',
SITE_BEGIN: '周年',
FOR_ONE_YEARS: '周年',
FOR_TWO_YEARS: '周年',
EVENT_NAME: '2018'
},
HEADERSTRING: {
FOREVER_VIP: '终',
YEARLY_VIP: '年',
MONTHLY_VIP: '月',
GUEST_VIP: '宾',
SITE_BEGIN: '0',
FOR_ONE_YEARS: '1',
FOR_TWO_YEARS: '2',
EVENT_NAME: '活动'
}
},
// data center
DATA_CENTER: {
ITEM_SCORE: '积分数据分析',
@@ -1518,6 +1636,7 @@
REQUEST_ACCEPT_TO: '您的响应被求种请求者接受 <a href=/requests/{{rid}}>{{rid}}</a>',
SCORE_EXCHANGE_INVITATION: '兑换了一张邀请函',
SCORETO_REMOVE_WARNING: '移除了一个 H&R 警告 <a href=/torrents/{{tid}}>{{tid}}</a>',
SCORETO_REQUEST_MEDAL: '申请勋章: {{medalDesc | translate}}',
ACTIVE_IDLE_ACCOUNT: '重新激活帐户状态',
DAILY_CHECK_IN: '每日签到',
SEED_TIMED: '做种时间获得的积分 <a href=/torrents/{{tid}}>{{tid}}</a>',
@@ -1531,7 +1650,7 @@
BAD_REQUEST: '请求错误',
FORBIDDEN: '请求禁止',
MADE_BAD_REQUEST: '您发起了一个无效的请求',
NOT_AUTHORIZED_THIS: '您无权访问此资源',
NOT_AUTHORIZED_THIS: '您无权访问此资源,如果您的 session 或 cookie 已过期,请 <a href="/authentication/signin">重新登录</a>。',
NOT_FOUND: '无法访问',
PAGE_NOT_FOUND: '没有找到页面或资源',
ACCESS_DENY: '您的当前IP被限制访问此资源如需帮助请给{{sNameDesc | translate}}发送 <strong><a href="/messages/send?to={{sName}}">消息</a></strong> 或 <strong><a href="mailto:{{sMail}}">邮件</a></strong>.'
@@ -1833,6 +1952,8 @@
ADMIN_PRESENT_USER_INVITATIONS: '`{{by.displayName}}` 赠送 `{{numbers}}` 个官方邀请函, 有效期 `{{days}}` 天',
ADMIN_REMOVE_USER_HNR_WARNING: '`{{by.displayName}}` 移除 H&R 警告, complete id: `{{complete}}`',
ADMIN_CREATE_USER_MAKER_GROUP: '`{{by.displayName}}` 创建用户资源小组: `-={{name}}=-`',
ADMIN_ADD_USER_MEDAL: '`{{by.displayName}}` 添加用户勋章: `{{medalName}}`',
ADMIN_REMOVE_USER_MEDAL: '`{{by.displayName}}` 移除用户勋章: `{{medalName}}`',
ADMIN_BAN_USER_INVITER: '`{{by.displayName}}` 改变帐户状态为: `{{status}}`, 理由: 邀请的用户[{{uname}}]因为[{{reason | translate}}]被禁止'
},
@@ -1875,7 +1996,9 @@
UPLOAD_ACCESS_DENY: '当前系统只接受资源制作小组上传种子',
READ_TORRENT_FILE_FAILD: '种子文件解析错误,请检查您的种子文件,看是否缺少某些必要信息',
MOVE_TORRENT_FILE_ERROR: '种子文件移动错误,请不要快速重复进行提交操作或者上传的种子文件已丢失',
YOU_ALREADY_CHECK_IN: '您今天已经签过到了,不能重复签到'
YOU_ALREADY_CHECK_IN: '您今天已经签过到了,不能重复签到',
USER_ALREADY_HAS_THIS_MEDAL: '该用户已经拥有了这枚勋章',
USER_HAS_NOT_THIS_MEDAL: '该用户还没有这枚勋章'
},
//server message string, content string support markdown and emoji

View File

@@ -13,7 +13,8 @@
state: 'admin',
type: 'dropdown',
roles: ['oper', 'admin'],
position: 10,
class: 'menu-left',
position: 20,
shouldDotClass: 'header-dot-class-admin'
});
}

View File

@@ -8,6 +8,15 @@
menuConfig.$inject = ['menuService'];
function menuConfig(menuService) {
menuService.addMenuItem('topbar', {
title: 'MENU_MORE',
state: 'more',
type: 'dropdown',
roles: ['*'],
class: 'sm-show',
position: 15
});
menuService.addMenu('account', {
roles: ['user']
});
@@ -26,32 +35,32 @@
faClass: 'text-mt'
});
menuService.addSubMenuItem('account', 'settings', {
title: 'EDIT_PROFILE_PIC',
state: 'settings.picture',
faIcon: 'fa-image',
faClass: 'text-mt'
});
menuService.addSubMenuItem('account', 'settings', {
title: 'EDIT_SIGNATURE',
state: 'settings.signature',
faIcon: 'fa-sign',
faClass: 'text-mt'
});
menuService.addSubMenuItem('account', 'settings', {
title: 'CHANGE_PASSWORD',
state: 'settings.password',
faIcon: 'fa-lock',
faClass: 'text-mt'
});
menuService.addSubMenuItem('account', 'settings', {
title: 'RESET_PASSKEY',
state: 'settings.passkey',
faIcon: 'fa-key',
faClass: 'text-mt'
});
// menuService.addSubMenuItem('account', 'settings', {
// title: 'EDIT_PROFILE_PIC',
// state: 'settings.picture',
// faIcon: 'fa-image',
// faClass: 'text-mt'
// });
//
// menuService.addSubMenuItem('account', 'settings', {
// title: 'EDIT_SIGNATURE',
// state: 'settings.signature',
// faIcon: 'fa-sign',
// faClass: 'text-mt'
// });
//
// menuService.addSubMenuItem('account', 'settings', {
// title: 'CHANGE_PASSWORD',
// state: 'settings.password',
// faIcon: 'fa-lock',
// faClass: 'text-mt'
// });
//
// menuService.addSubMenuItem('account', 'settings', {
// title: 'RESET_PASSKEY',
// state: 'settings.passkey',
// faIcon: 'fa-key',
// faClass: 'text-mt'
// });
}
}());

View File

@@ -124,23 +124,23 @@
/**
* $scope.$watch($('#nav-top-menu').width())
*/
$scope.$watch(function () {
return $('#nav-top-menu').width();
}, function (newVal, oldVal) {
if (newVal) {
if (window.outerWidth > 767 && window.outerWidth < 992) { //sm screen
if (newVal > 540) {
$('a[ui-sref="chat"]').css('display', 'none');
}
} else if (window.outerWidth > 991 && window.outerWidth < 1200) { //md screen
if (newVal > 580) {
$('a[ui-sref="chat"]').css('display', 'none');
}
} else {
$('a[ui-sref="chat"]').css('display', 'block');
}
}
});
// $scope.$watch(function () {
// return $('#nav-top-menu').width();
// }, function (newVal, oldVal) {
// if (newVal) {
// if (window.outerWidth > 767 && window.outerWidth < 992) { //sm screen
// if (newVal > 540) {
// $('a[ui-sref="chat"]').css('display', 'none');
// }
// } else if (window.outerWidth > 991 && window.outerWidth < 1200) { //md screen
// if (newVal > 580) {
// $('a[ui-sref="chat"]').css('display', 'none');
// }
// } else {
// $('a[ui-sref="chat"]').css('display', 'block');
// }
// }
// });
/**
* auth-user-changed

View File

@@ -24,6 +24,7 @@
element.css('bottom', '20px');
element.css('width', '36px');
element.css('height', '36px');
element.css('z-index', 1);
element.css('border-radius', '50%');
element.css('backgroundColor', 'rgba(255, 255, 255, 0.8)');

View File

@@ -15,23 +15,6 @@
}
}
.header-dot-class-admin {
display: none;
position: absolute;
width: 10px;
height: 10px;
top: 12px;
right: 25px;
border-radius: 50%;
border: solid 1px #fff;
&.new-torrent {
background-color: @brand-info;
}
&.opened-tickets {
background-color: @brand-danger !important;
}
}
.badge-class-admin-torrents {
display: none;
}

View File

@@ -3,98 +3,122 @@
/**
margin-top
*/
.margin-top-2 { margin-top: 2px; }
.margin-top-5 { margin-top: 5px; }
.margin-top-10 { margin-top: 10px; }
.margin-top-15 { margin-top: 15px; }
.margin-top-20 { margin-top: 20px; }
.margin-top-30 { margin-top: 30px; }
.margin-top-40 { margin-top: 40px; }
.margin-top-50 { margin-top: 50px; }
.margin-top-100 { margin-top: 100px; }
.margin-top-2 { margin-top: 2px !important; }
.margin-top-5 { margin-top: 5px !important; }
.margin-top-10 { margin-top: 10px !important; }
.margin-top-15 { margin-top: 15px !important; }
.margin-top-20 { margin-top: 20px !important; }
.margin-top-30 { margin-top: 30px !important; }
.margin-top-40 { margin-top: 40px !important; }
.margin-top-50 { margin-top: 50px !important; }
.margin-top-100 { margin-top: 100px !important; }
/**
margin-bottom
*/
.margin-bottom-5 { margin-bottom: 5px; }
.margin-bottom-10 { margin-bottom: 10px; }
.margin-bottom-15 { margin-bottom: 15px; }
.margin-bottom-20 { margin-bottom: 20px; }
.margin-bottom-30 { margin-bottom: 30px; }
.margin-bottom-40 { margin-bottom: 40px; }
.margin-bottom-50 { margin-bottom: 50px; }
.margin-bottom-5 { margin-bottom: 5px !important; }
.margin-bottom-10 { margin-bottom: 10px !important; }
.margin-bottom-15 { margin-bottom: 15px !important; }
.margin-bottom-20 { margin-bottom: 20px !important; }
.margin-bottom-30 { margin-bottom: 30px !important; }
.margin-bottom-40 { margin-bottom: 40px !important; }
.margin-bottom-50 { margin-bottom: 50px !important; }
/**
margin-right
*/
.margin-right-10 { margin-right: 10px; }
.margin-right-20 { margin-right: 20px; }
.margin-right-30 { margin-right: 30px; }
.margin-right-40 { margin-right: 40px; }
.margin-right-50 { margin-right: 50px; }
.margin-right-10 { margin-right: 10px !important; }
.margin-right-20 { margin-right: 20px !important; }
.margin-right-30 { margin-right: 30px !important; }
.margin-right-40 { margin-right: 40px !important; }
.margin-right-50 { margin-right: 50px !important; }
/**
margin-left
*/
.margin-left-10 { margin-left: 10px; }
.margin-left-20 { margin-left: 20px; }
.margin-left-30 { margin-left: 30px; }
.margin-left-40 { margin-left: 40px; }
.margin-left-50 { margin-left: 50px; }
.margin-left-80 { margin-left: 80px; }
.margin-left-100 { margin-left: 100px; }
.margin-left-10 { margin-left: 10px !important; }
.margin-left-20 { margin-left: 20px !important; }
.margin-left-30 { margin-left: 30px !important; }
.margin-left-40 { margin-left: 40px !important; }
.margin-left-50 { margin-left: 50px !important; }
.margin-left-80 { margin-left: 80px !important; }
.margin-left-100 { margin-left: 100px !important; }
.margin-left-m-20 { margin-left: -20px; }
.margin-left-m-20 { margin-left: -20px !important; }
/**
padding-left
*/
.padding-left-5 { padding-left: 5px !important; }
.padding-left-10 { padding-left: 10px !important; }
.padding-left-15 { padding-left: 15px !important; }
.padding-left-20 { padding-left: 20px !important; }
.padding-left-30 { padding-left: 30px !important; }
.padding-left-40 { padding-left: 40px !important; }
.padding-left-50 { padding-left: 50px !important; }
.padding-left-100 { padding-left: 100px !important; }
/**
padding-right
*/
.padding-right-5 { padding-right: 5px !important; }
.padding-right-10 { padding-right: 10px !important; }
.padding-right-15 { padding-right: 15px !important; }
.padding-right-20 { padding-right: 20px !important; }
.padding-right-30 { padding-right: 30px !important; }
.padding-right-40 { padding-right: 40px !important; }
.padding-right-50 { padding-right: 50px !important; }
.padding-right-100 { padding-right: 100px !important; }
/**
padding-top
*/
.padding-top-5 { padding-top: 5px; }
.padding-top-10 { padding-top: 10px; }
.padding-top-15 { padding-top: 15px; }
.padding-top-20 { padding-top: 20px; }
.padding-top-30 { padding-top: 30px; }
.padding-top-40 { padding-top: 40px; }
.padding-top-50 { padding-top: 50px; }
.padding-top-100 { padding-top: 100px; }
.padding-top-5 { padding-top: 5px !important; }
.padding-top-10 { padding-top: 10px !important; }
.padding-top-15 { padding-top: 15px !important; }
.padding-top-20 { padding-top: 20px !important; }
.padding-top-30 { padding-top: 30px !important; }
.padding-top-40 { padding-top: 40px !important; }
.padding-top-50 { padding-top: 50px !important; }
.padding-top-100 { padding-top: 100px !important; }
/**
padding-bottom
*/
.padding-bottom-5 { padding-bottom: 5px; }
.padding-bottom-10 { padding-bottom: 10px; }
.padding-bottom-15 { padding-bottom: 15px; }
.padding-bottom-20 { padding-bottom: 20px; }
.padding-bottom-30 { padding-bottom: 30px; }
.padding-bottom-40 { padding-bottom: 40px; }
.padding-bottom-50 { padding-bottom: 50px; }
.padding-bottom-5 { padding-bottom: 5px !important; }
.padding-bottom-10 { padding-bottom: 10px !important; }
.padding-bottom-15 { padding-bottom: 15px !important; }
.padding-bottom-20 { padding-bottom: 20px !important; }
.padding-bottom-30 { padding-bottom: 30px !important; }
.padding-bottom-40 { padding-bottom: 40px !important; }
.padding-bottom-50 { padding-bottom: 50px !important; }
@media (min-width: @screen-xxs-min) {
.margin-xxs-bottom-0 { margin-bottom: 0; }
.margin-xxs-bottom-10 { margin-bottom: 10px; }
.margin-xxs-bottom-20 { margin-bottom: 20px; }
.margin-xxs-bottom-0 { margin-bottom: 0 !important; }
.margin-xxs-bottom-10 { margin-bottom: 10px !important; }
.margin-xxs-bottom-20 { margin-bottom: 20px !important; }
}
@media (min-width: @screen-xs-min) {
.margin-xs-bottom-0 { margin-bottom: 0; }
.margin-xs-bottom-10 { margin-bottom: 10px; }
.margin-xs-bottom-20 { margin-bottom: 20px; }
.margin-xs-bottom-0 { margin-bottom: 0 !important; }
.margin-xs-bottom-10 { margin-bottom: 10px !important; }
.margin-xs-bottom-20 { margin-bottom: 20px !important; }
}
@media (min-width: @screen-sm-min) {
.margin-sm-bottom-0 { margin-bottom: 0; }
.margin-sm-bottom-10 { margin-bottom: 10px; }
.margin-sm-bottom-20 { margin-bottom: 20px; }
.margin-sm-bottom-0 { margin-bottom: 0 !important; }
.margin-sm-bottom-10 { margin-bottom: 10px !important; }
.margin-sm-bottom-20 { margin-bottom: 20px !important; }
}
@media (min-width: @screen-md-min) {
.margin-md-bottom-0 { margin-bottom: 0; }
.margin-md-bottom-10 { margin-bottom: 10px; }
.margin-md-bottom-20 { margin-bottom: 20px; }
.margin-md-bottom-0 { margin-bottom: 0 !important; }
.margin-md-bottom-10 { margin-bottom: 10px !important; }
.margin-md-bottom-20 { margin-bottom: 20px !important; }
}
@media (min-width: @screen-lg-min) {
.margin-lg-bottom-0 { margin-bottom: 0; }
.margin-lg-bottom-10 { margin-bottom: 10px; }
.margin-lg-bottom-20 { margin-bottom: 20px; }
.margin-lg-bottom-0 { margin-bottom: 0 !important; }
.margin-lg-bottom-10 { margin-bottom: 10px !important; }
.margin-lg-bottom-20 { margin-bottom: 20px !important; }
}

View File

@@ -25,7 +25,7 @@
}
.xxs-show .xs-show, .sm-show, .md-show, .lg-show {
display: none;
display: none !important;
}
@media (max-width: @screen-xs) {

View File

@@ -1,21 +1,22 @@
@import (reference) "mt-var.less";
.width-50, .min-width-50, .btn-width-50 { min-width: 50px !important; }
.width-60, .min-width-60, .btn-width-60 { min-width: 60px !important; }
.width-70, .min-width-70, .btn-width-70 { min-width: 70px !important; }
.width-80, .min-width-80, .btn-width-80 { min-width: 80px !important; }
.width-90, .min-width-90, .btn-width-90 { min-width: 90px !important; }
.width-100, .min-width-100, .btn-width-100 { min-width: 100px !important; }
.width-120, .min-width-120, .btn-width-120 { min-width: 120px !important; }
.width-140, .min-width-140, .btn-width-140 { min-width: 140px !important; }
.width-150, .min-width-150, .btn-width-150 { min-width: 150px !important; }
.width-160, .min-width-160, .btn-width-160 { min-width: 160px !important; }
.width-170, .min-width-170, .btn-width-170 { min-width: 170px !important; }
.width-180, .min-width-180, .btn-width-180 { min-width: 180px !important; }
.width-200, .min-width-200, .btn-width-200 { min-width: 200px !important; }
.width-300, .min-width-300 { min-width: 300px !important; }
.width-400, .min-width-400 { min-width: 400px !important; }
.width-500, .min-width-500 { min-width: 500px !important; }
.width-50, .min-width-50, .btn-min-width-50 { min-width: 50px !important; }
.width-60, .min-width-60, .btn-min-width-60 { min-width: 60px !important; }
.width-70, .min-width-70, .btn-min-width-70 { min-width: 70px !important; }
.width-80, .min-width-80, .btn-min-width-80 { min-width: 80px !important; }
.width-90, .min-width-90, .btn-min-width-90 { min-width: 90px !important; }
.width-100, .min-width-100, .btn-min-width-100 { min-width: 100px !important; }
.width-120, .min-width-120, .btn-min-width-120 { min-width: 120px !important; }
.width-140, .min-width-140, .btn-min-width-140 { min-width: 140px !important; }
.width-150, .min-width-150, .btn-min-width-150 { min-width: 150px !important; }
.width-160, .min-width-160, .btn-min-width-160 { min-width: 160px !important; }
.width-170, .min-width-170, .btn-min-width-170 { min-width: 170px !important; }
.width-180, .min-width-180, .btn-min-width-180 { min-width: 180px !important; }
.width-190, .min-width-190, .btn-min-width-190 { min-width: 190px !important; }
.width-200, .min-width-200, .btn-min-width-200 { min-width: 200px !important; }
.width-300, .min-width-300 { min-width: 300px !important; }
.width-400, .min-width-400 { min-width: 400px !important; }
.width-500, .min-width-500 { min-width: 500px !important; }
.max-width-10 { max-width: 10px !important; }
.max-width-20 { max-width: 20px !important; }
@@ -36,6 +37,24 @@
.max-width-400 { max-width: 400px !important; }
.max-width-500 { max-width: 500px !important; }
.width-50 { width: 50px !important; }
.width-60 { width: 60px !important; }
.width-70 { width: 70px !important; }
.width-80 { width: 80px !important; }
.width-90 { width: 90px !important; }
.width-100 { width: 100px !important; }
.width-120 { width: 120px !important; }
.width-140 { width: 140px !important; }
.width-150 { width: 150px !important; }
.width-160 { width: 160px !important; }
.width-170 { width: 170px !important; }
.width-180 { width: 180px !important; }
.width-190 { width: 190px !important; }
.width-200 { width: 200px !important; }
.width-300 { width: 300px !important; }
.width-400 { width: 400px !important; }
.width-500 { width: 500px !important; }
@media (min-width: @screen-xxs-min) {
.min-xss-width-10 { min-width: 10px !important; }
.min-xss-width-20 { min-width: 20px !important; }

View File

@@ -50,22 +50,11 @@ body {
cursor: pointer;
font-size: 12px;
color: @mt-base-color;
text-shadow: 0 0 1px #000,-0 -0 1px #000;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.9);
border-radius: 4px;
background-color: transparent;
margin-top: 16px;
padding: 2px 5px;
margin: 0 5px;
white-space: nowrap;
overflow: hidden;
box-sizing: border-box;
@media (min-width: @screen-md) and (max-width: @screen-md-max) {
width: 120px;
}
@media (min-width: @screen-lg) {
width: 180px;
}
max-width: 180px;
span {
display: inline-block;
padding-left: 100%; /* show the marquee just outside the paragraph */
@@ -87,23 +76,6 @@ body {
}
}
.header-red-dot {
position: absolute;
width: 10px;
height: 10px;
top: 12px;
left: 35px;
border-radius: 50%;
border: solid 1px #fff;
&.bg-msg {
background-color: @btn-info-bg !important;
}
&.bg-hnr {
background-color: @btn-danger-bg;
}
}
.user-header-dropdown-toggle {
.img {
position: relative;
@@ -449,25 +421,6 @@ body {
}
}
.score-level {
cursor: pointer;
color: #FF6600;
> kbd {
font-size: 12px;
background-color: #FF6600;
}
}
.score-level-default {
cursor: pointer;
color: #333 !important;
> kbd {
font-size: 12px;
color: #333 !important;
background-color: #eee !important;
}
}
.menu-score {
position: absolute;
right: 10px;
@@ -521,7 +474,7 @@ body {
color: @brand-success;
background-color: @alert-success-bg;
font-size: 12px;
border: solid 1px @brand-success;
border: solid 1px @brand-success;
border-radius: 3px;
}
}
@@ -1457,12 +1410,24 @@ body {
> a {
padding-left: 10px;
padding-right: 10px;
.header-red-dot {
left: 30px;
}
.header-dot-class-admin {
right: 16px;
}
}
}
@media (min-width: @screen-md) and (max-width: @screen-md-max) {
> a {
padding-left: 12px;
padding-right: 12px;
.header-red-dot {
left: 32px;
}
.header-dot-class-admin {
right: 18px;
}
}
}
}
@@ -1475,6 +1440,48 @@ body {
}
}
}
.menu-left {
.dropdown-menu {
@media (min-width: @screen-sm) and (max-width: @screen-sm-max) {
right: 0;
left: auto;
}
}
}
}
.header-dot-class-admin {
display: none;
position: absolute;
width: 10px;
height: 10px;
top: 12px;
right: 21px;
border-radius: 50%;
border: solid 1px #fff;
&.new-torrent {
background-color: @brand-info;
}
&.opened-tickets {
background-color: @brand-danger !important;
}
}
.header-red-dot {
position: absolute;
width: 10px;
height: 10px;
top: 12px;
left: 35px;
border-radius: 50%;
border: solid 1px #fff;
&.bg-msg {
background-color: @btn-info-bg !important;
}
&.bg-hnr {
background-color: @btn-danger-bg;
}
}
.torrent-info-tabs {
@@ -1821,13 +1828,6 @@ body {
color: @mt-base-color;
}
.admin-user-info {
hr {
margin-bottom: 15px;
margin-top: 5px;
}
}
.lang-list {
margin-top: 5px;
padding-left: 5px;
@@ -1934,15 +1934,6 @@ body {
color: @mt-base-color;
}
.curr-score {
color: @mt-base-color;
font-size: 48px;
}
.score-progress {
margin-bottom: 2px;
}
.mt-title {
font-size: 18px;
}

View File

@@ -0,0 +1,26 @@
(function () {
'use strict';
angular
.module('core')
.factory('MiddleDataServices', MiddleDataServices);
function MiddleDataServices() {
var middleData = [];
var service = {
setData: setData,
getData: getData
};
return service;
function setData(dataName, data) {
middleData[dataName] = data;
}
function getData(dataName) {
return middleData[dataName];
}
}
}());

View File

@@ -0,0 +1,58 @@
(function () {
'use strict';
// Authentication service for user variables
angular
.module('core')
.factory('SafeColorsServices', SafeColorsServices);
function SafeColorsServices() {
var colors = [
'#000000', '#000033', '#000066', '#000099', '#0000CC', '#0000FF',
'#003300', '#003333', '#003366', '#003399', '#0033CC', '#0033FF',
'#006600', '#006633', '#006666', '#006699', '#0066CC', '#0066FF',
'#009900', '#009933', '#009966', '#009999', '#0099CC', '#0099FF',
'#330000', '#330033', '#330066', '#330099', '#3300CC', '#3300FF',
'#333300', '#333333', '#333366', '#333399', '#3333CC', '#3333FF',
'#336600', '#336633', '#336666', '#336699', '#3366CC', '#3366FF',
'#339900', '#339933', '#339966', '#339999', '#3399CC', '#3399FF',
'#660000', '#660033', '#660066', '#660099', '#6600CC', '#6600FF',
'#663300', '#663333', '#663366', '#663399', '#6633CC', '#6633FF',
'#666600', '#666633', '#666666', '#666699', '#6666CC', '#6666FF',
'#669900', '#669933', '#669966', '#669999', '#6699CC', '#6699FF',
'#990000', '#990033', '#990066', '#990099', '#9900CC', '#9900FF',
'#993300', '#993333', '#993366', '#993399', '#9933CC', '#9933FF',
'#996600', '#996633', '#996666', '#996699', '#9966CC', '#9966FF',
'#999900', '#999933', '#999966', '#999999', '#9999CC', '#9999FF',
'#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF',
'#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF',
'#CC6600', '#CC6633', '#CC6666', '#CC6699', '#CC66CC', '#CC66FF',
'#CC9900', '#CC9933', '#CC9966', '#CC9999', '#CC99CC', '#CC99FF',
'#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF',
'#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF',
'#FF6600', '#FF6633', '#FF6666', '#FF6699', '#FF66CC', '#FF66FF',
'#FF9900', '#FF9933', '#FF9966', '#FF9999', '#FF99CC', '#FF99FF'
];
var service = {
getSafeColor: getSafeColor
};
return service;
/**
* getSafeColor
* @returns {*}
*/
function getSafeColor() {
return colors[Math.floor((Math.random() * 144) + 1)];
}
}
}());

View File

@@ -61,7 +61,7 @@
<h3 translate="WARNING_POPUP_STRING"></h3>
</div>
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 text-center">
<button class="warning_popup_close btn btn-lg btn-success btn-width-100 margin-top-20">{{'BUTTON_MESSAGE_CLOSE' | translate}}</button>
<button class="warning_popup_close btn btn-lg btn-success btn-min-width-100 margin-top-20">{{'BUTTON_MESSAGE_CLOSE' | translate}}</button>
</div>
</div>
</div>

View File

@@ -18,7 +18,7 @@
<a ng-switch-when="dropdown" class="dropdown-toggle" uib-dropdown-toggle role="button" alt="{{item.linkState}}">
<span menu-title="{{item.title}}">{{::item.title}}</span>
<span ng-if="item.shouldDotClass" class="{{item.shouldDotClass}}"></span>
&nbsp;<span class="caret"></span>
<span class="caret"></span>
</a>
<ul ng-switch-when="dropdown" class="dropdown-menu">
<li ui-sref-active="active" ng-repeat="subitem in item.items | orderBy: 'position'" class="menu-parent"
@@ -44,20 +44,13 @@
</li>
</ul>
<ul class="nav navbar-nav navbar-right" ng-if="vm.authentication.user">
<li class="scroll-info xs-hide sm-hide" ui-sref="status.account" ng-if="vm.authentication.user">
<span>
{{'TABLE_FIELDS.RATIO' | translate}}: {{vm.authentication.user.ratio | ratio}}, 
{{'TABLE_FIELDS.LEVEL' | translate}}: {{vm.scoreLevelData.currLevel}}, 
{{'TABLE_FIELDS.SEEDED' | translate}}: {{vm.authentication.user.seeded}}, 
{{'TABLE_FIELDS.LEECHED' | translate}}: {{vm.authentication.user.leeched}}</span>
</li>
<li class="dropdown" uib-dropdown>
<a class="dropdown-toggle user-header-dropdown-toggle" uib-dropdown-toggle role="button" alt="status.account">
<img ng-src="{{vm.authentication.user.profileImageURL}}" alt="{{vm.authentication.user.displayName}}"
class="header-profile-image"/>
<span class="sm-hide" ng-bind="vm.authentication.user.displayName"></span> <b class="caret"></b>
<span class="sm-hide" ng-bind="vm.authentication.user.displayName"></span><b class="caret"></b>
<span class="header-red-dot" ng-if="vm.unreadCount>0 || vm.user.hnr_warning>0"
ng-class="{'bg-hnr': vm.user.hnr_warning>0, 'bg-msg': vm.unreadCount>0}"></span>
ng-class="{'bg-msg': vm.unreadCount>0, 'bg-hnr': vm.user.hnr_warning>0}"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li class="lang-list">
@@ -66,6 +59,15 @@
ng-class="{'curr-language': vm.langService.getLang() == l.name}"></span>
</li>
<li class="divider"></li>
<li class="scroll-info" ui-sref="status.account" ng-if="vm.authentication.user">
<span>
{{'TABLE_FIELDS.RATIO' | translate}}: {{vm.authentication.user.ratio | ratio}}, 
{{'TABLE_FIELDS.LEVEL' | translate}}: {{vm.scoreLevelData.currLevel}}, 
{{'TABLE_FIELDS.SEEDED' | translate}}: {{vm.authentication.user.seeded}}, 
{{'TABLE_FIELDS.LEECHED' | translate}}: {{vm.authentication.user.leeched}}
</span>
</li>
<li class="divider"></li>
<li ui-sref-active="active" ng-repeat="item in vm.followMenu.items" class="menu-parent">
<a ui-sref="{{item.state}}">
<i class="fa fa-fw {{item.faIcon}} {{item.faClass}}"></i><span ng-bind="item.title" menu-title="{{item.title}}"></span>
@@ -79,7 +81,12 @@
</a>
<span class="badge menu-badge badge_info" ng-show="vm.unreadCount>0">{{vm.unreadCount}}</span>
</li>
<li ui-sref-active="active" ng-repeat="item in vm.statusMenu.items" class="menu-parent">
<li ui-sref-active="active" ng-repeat="item in vm.statusMenu.items" ng-if="$index==0" class="menu-parent">
<a ui-sref="{{item.state}}">
<i class="fa fa-fw {{item.faIcon}} {{item.faClass}}"></i><span ng-bind="item.title" menu-title="{{item.title}}"></span>
</a>
</li>
<li ui-sref-active="active" ng-repeat="item in vm.statusMenu.items" ng-if="$index==1" class="menu-parent">
<a ui-sref="{{item.state}}">
<i class="fa fa-fw {{item.faIcon}} {{item.faClass}}"></i><span ng-bind="item.title" menu-title="{{item.title}}"></span>
</a>
@@ -144,7 +151,7 @@
</div>
</div>
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 text-center margin-top-10">
<button class="must_read_popup_close btn btn-success btn-width-100">{{'BUTTON_UPLOADED_POPUP_CLOSE' | translate}}</button>
<button class="must_read_popup_close btn btn-success btn-min-width-100">{{'BUTTON_UPLOADED_POPUP_CLOSE' | translate}}</button>
</div>
</div>
</div>

View File

@@ -61,7 +61,7 @@
ng-keydown="vm.onSearchKeyDown($event);"
aria-label="search" placeholder="Search">
<button class="btn btn-width-100 btn-search" id="search-button" aria-label="Search"
<button class="btn btn-min-width-100 btn-search" id="search-button" aria-label="Search"
mouse-enter-toggle-class="btn-success" base-class="btn-default"
ng-click="vm.doGlobalSearch()">
{{'BTN_GLOBAL_SEARCH' | translate}}
@@ -252,7 +252,7 @@
<div class="vip-more margin-bottom-10">
<a ui-sref="vip.rules">{{'HOME.MORE_VIP_RULES_AND_RIGHT' | translate}}</a>
</div>
<a ui-sref="vip.donate" class="btn btn-width-150 btn-mt-success-light margin-bottom-20"
<a ui-sref="vip.donate" class="btn btn-min-width-150 btn-mt-success-light margin-bottom-20"
mt-scale-by-mouse="{scale: 1.2, duration: '.5s'}">
{{'HOME.BTN_JOIN_VIP' | translate}}
</a>

View File

@@ -46,7 +46,7 @@
<!-- Application CSS Files -->
{{#each cssFiles}}<link rel="stylesheet" href="/{{this}}">{{/each}}
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-oi8o31xSQq8S0RpBcb4FaLB8LJi9AT8oIdmS1QldR8Ui7KUQjNAnDlJjp55Ba8FG" crossorigin="anonymous">
<link rel="stylesheet" href="/web-fonts-with-css/css/fontawesome-all.min.css">
</head>
<body class="ng-cloak body-backdrop">

View File

@@ -13,7 +13,18 @@
title: 'MENU_FORUMS',
state: 'forums.list',
roles: ['*'],
position: 5
class: 'sm-hide',
position: 6
});
//add to more
menuService.addSubMenuItem('topbar', 'more', {
title: 'MENU_FORUMS',
state: 'forums.list',
roles: ['*'],
faIcon: 'fa-bars',
faClass: 'text-mt',
position: 2
});
}
}());

View File

@@ -274,10 +274,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(t.content);
e.$options.hideable = true;
@@ -372,10 +372,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(r.content);
e.$options.hideable = true;

View File

@@ -1,7 +1,7 @@
<section class="container padding-top-10" ng-controller="ForumsAdminController as vm" ng-init="vm.init();">
<div class="row margin-top-20 forum-list">
<div class="col-md-10 col-md-offset-1">
<button class="btn btn-success btn-width-100" ng-click="vm.popupCreateForum($event)">  {{ 'FORUMS.BTN_ADD_FORUM' | translate }}  </button>
<button class="btn btn-success btn-min-width-100" ng-click="vm.popupCreateForum($event)">  {{ 'FORUMS.BTN_ADD_FORUM' | translate }}  </button>
</div>
<div class="col-sm-10 col-sm-offset-1 margin-top-30">
@@ -112,17 +112,17 @@
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-success btn-width-100"
<button type="submit" class="btn btn-success btn-min-width-100"
ng-click="vm.createNewForum();"
ng-hide="vm.isEdit"
ng-disabled="!vm.forum.name || !vm.forum.desc ">{{'FORUMS.BTN_ADD' | translate}}
</button>
<button type="submit" class="btn btn-success btn-width-100"
<button type="submit" class="btn btn-success btn-min-width-100"
ng-click="vm.editForum();"
ng-show="vm.isEdit"
ng-disabled="!vm.forum.name || !vm.forum.desc ">{{'FORUMS.BTN_EDIT' | translate}}
</button>
<button type="submit" class="btn btn-success btn-width-100"
<button type="submit" class="btn btn-success btn-min-width-100"
ng-click="vm.deleteForum();"
ng-show="vm.isEdit"
ng-disabled="!vm.forum.name || !vm.forum.desc ">{{'FORUMS.BTN_DELETE' | translate}}
@@ -140,7 +140,7 @@
placeholder="{{ 'STATUS_FIELD.USERNAME' | translate }}" autofocus>
</div>
<div class="margin-top-10">
<button class="btn btn-default btn-width-80" ng-disabled="!vm.addModeratorPopover.username"
<button class="btn btn-default btn-min-width-80" ng-disabled="!vm.addModeratorPopover.username"
ng-click="vm.addModerator();">{{ 'FORUMS.BTN_ADD' | translate }}
</button>
</div>

View File

@@ -59,7 +59,7 @@
{{ 'MARKDOWN_LINK' | translate }}
</a>
</div>
<button type="submit" class="btn btn-success btn-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_TOPIC' | translate}}
<button type="submit" class="btn btn-success btn-min-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_TOPIC' | translate}}
</button>
</form>
</div>

View File

@@ -29,9 +29,9 @@
</div>
<div class="box-post-btn">
<div ng-if="!vm.topic.readOnly || vm.canEdit(vm.topic) || vm.isOwner(vm.topic)">
<a class="btn btn-success btn-width-100"
<a class="btn btn-success btn-min-width-100"
href="#" ng-click="vm.beginPostReply();">{{'FORUMS.BTN_POST_NEW_REPLY' | translate}}</a>
<a class="btn btn-default btn-width-100"
<a class="btn btn-default btn-min-width-100"
href="#" ng-if="vm.canEdit(vm.topic) || vm.isOwner(vm.topic)"
ng-click="vm.toggleReadonly(vm.topic);">{{ vm.topic.readOnly ? 'FORUMS.BTN_UNSET_READONLY' : 'FORUMS.BTN_SET_READONLY' | translate}}</a>
</div>
@@ -301,7 +301,7 @@
{{ 'MARKDOWN_LINK' | translate }}
</a>
</div>
<button type="submit" class="btn btn-success btn-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_REPLY' | translate}}
<button type="submit" class="btn btn-success btn-min-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_REPLY' | translate}}
</button>
</form>
</div>

View File

@@ -92,7 +92,7 @@
</ul>
</div>
<div class="box-post-btn">
<a class="btn btn-success btn-width-100"
<a class="btn btn-success btn-min-width-100"
ng-if="!vm.forum.readOnly || vm.canEdit(vm.forum)"
ui-sref="forums.post({forumId: vm.forum._id})">{{'FORUMS.BTN_POST_NEW_TOPIC' | translate}}</a>
<h5 class="text-danger text-uppercase" translate="FORUMS.READ_ONLY_POST"

View File

@@ -13,11 +13,11 @@
<div class="margin-bottom-10">
<form class="form-inline">
<div class="form-group">
<input type="email" class="form-control width-300" id="title" name="title"
<input type="email" class="form-control min-width-300" id="title" name="title"
ng-model="vm.invitationFields.email" placeholder="{{ 'INPUT_EMAIL' | translate }}" autofocus>
</div>
<button type="submit" class="btn btn-success btn-width-100"
<button type="submit" class="btn btn-success btn-min-width-100"
ng-disabled="!vm.invitationFields.email"
ng-click="vm.sendOfficialInvitation();">
{{ 'BUTTON_INVITE' | translate }}
@@ -77,8 +77,8 @@
</td>
<td class="col-sm-1 text-center">{{r.token}}</td>
<td class="col-sm-3 text-center">{{r.to_email}}</td>
<td class="col-sm-2 text-center width-120">{{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="col-sm-2 text-center width-120">{{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="col-sm-2 text-center min-width-120">{{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="col-sm-2 text-center min-width-120">{{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="col-sm-1 text-center" ng-if="r.to_user"
uib-popover-template="vm.subuserPopover.templateUrl"
popover-append-to-body="true"

View File

@@ -67,8 +67,8 @@
{{'INVITATION.TYPE_'+r.type.toUpperCase() | translate}}
</span>
</td>
<td class="text-center width-120">{{r.createdat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center width-120">{{r.expiresat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center min-width-120">{{r.createdat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center min-width-120">{{r.expiresat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center">
<button class="btn btn-default btn-xs" js-popover
uib-popover-template="vm.invitePopover.templateUrl"
@@ -154,8 +154,8 @@
<td class="text-center">{{$index+1}}</td>
<td class="text-center">{{r.token}}</td>
<td class="text-center">{{r.to_email}}</td>
<td class="text-center width-120">{{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center width-120">{{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center min-width-120">{{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center min-width-120">{{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}}</td>
<td class="text-center" ng-if="r.to_user"
uib-popover-template="vm.subuserPopover.templateUrl"
popover-append-to-body="true"

View File

@@ -0,0 +1,31 @@
(function () {
'use strict';
angular
.module('medals')
.run(menuConfig);
menuConfig.$inject = ['menuService'];
function menuConfig(menuService) {
// Set top bar menu items
menuService.addMenuItem('topbar', {
title: 'MENU_MEDALS',
state: 'medals.list',
roles: ['*'],
class: 'sm-hide',
position: 5
});
//add to more
menuService.addSubMenuItem('topbar', 'more', {
title: 'MENU_MEDALS',
state: 'medals.list',
roles: ['*'],
faIcon: 'fa-shield-alt',
faClass: 'text-mt',
position: 1
});
}
}());

View File

@@ -0,0 +1,43 @@
(function () {
'use strict';
angular
.module('medals.routes')
.config(routeConfig);
routeConfig.$inject = ['$stateProvider'];
function routeConfig($stateProvider) {
$stateProvider
.state('medals', {
abstract: true,
url: '/medals',
template: '<ui-view/>',
data: {
roles: ['user', 'oper', 'admin']
}
})
.state('medals.list', {
url: '',
templateUrl: '/modules/medals/client/views/list.client.view.html',
data: {
pageTitle: 'PAGETITLE.MEDALS'
}
})
.state('medals.view', {
url: '/:medalName',
templateUrl: '/modules/medals/client/views/view.client.view.html',
data: {
medal: null,
pageTitle: 'PAGETITLE.MEDALS'
}
})
.state('medals.request', {
url: '/:medalName',
templateUrl: '/modules/medals/client/views/request.client.view.html',
data: {
pageTitle: 'PAGETITLE.MEDALS'
}
});
}
}());

View File

@@ -0,0 +1,262 @@
(function () {
'use strict';
angular
.module('medals')
.controller('MedalsController', MedalsController);
MedalsController.$inject = ['$scope', '$rootScope', '$state', '$stateParams', '$translate', 'MeanTorrentConfig', 'MedalsService', 'NotifycationService', 'DebugConsoleService',
'$timeout', 'MedalsInfoServices', 'localStorageService', 'marked', 'MiddleDataServices', 'Authentication', 'UsersService', 'ModalConfirmService'];
function MedalsController($scope, $rootScope, $state, $stateParams, $translate, MeanTorrentConfig, MedalsService, NotifycationService, mtDebug,
$timeout, MedalsInfoServices, localStorageService, marked, MiddleDataServices, Authentication, UsersService, ModalConfirmService) {
var vm = this;
vm.user = Authentication.user;
vm.medalsConfig = MeanTorrentConfig.meanTorrentConfig.medals;
vm.homeConfig = MeanTorrentConfig.meanTorrentConfig.home;
vm.itemsPerPageConfig = MeanTorrentConfig.meanTorrentConfig.itemsPerPage;
/**
* initTopBackground
*/
vm.initTopBackground = function () {
var url = localStorageService.get('body_background_image') || vm.homeConfig.bodyBackgroundImage;
$('.backdrop').css('backgroundImage', 'url("' + url + '")');
};
/**
* getMedals
*/
vm.getMedals = function () {
MedalsService.count(function (res) {
vm.medals = MedalsInfoServices.getMedalsAll();
angular.forEach(vm.medals.items, function (md) {
md.count = 0;
for (var i = 0; i < res.length; i++) {
if (md.name === res[i]._id) {
md.count = res[i].count;
break;
}
}
});
vm.medals.typesLength = Object.keys(vm.medals.types).length;
vm.medals.itemCount = vm.medals.items.map(function (x) {
return x.count;
}).reduce(function (a, b) {
return a + b;
});
// MiddleDataServices.setData('medals', vm.medals);
mtDebug.info(vm.medals);
vm.getUserMedals();
});
};
/**
* getUserMedals
*/
vm.getUserMedals = function () {
MedalsService.query({
userId: vm.user._id
}, function (medals) {
vm.userMedals = medals;
});
};
/**
* hasMedal
* @param md
* @returns {boolean}
*/
vm.hasMedal = function (md) {
var has = false;
if (md) {
angular.forEach(vm.userMedals, function (m) {
if (m.medalName === md.name) {
has = true;
}
});
}
return has;
};
/**
* getMedalOverviewContent
* @returns {*}
*/
vm.getMedalOverviewContent = function () {
var str = $translate.instant('MEDALS.MEDALS_OVERVIEW');
return marked(str, {sanitize: true});
};
/**
* initMedal
*/
vm.getMedal = function () {
MedalsService.count({
mName: $state.params.medalName
}, function (res) {
vm.medal = MedalsInfoServices.getMedal($state.params.medalName);
vm.medal.count = res[0].count;
mtDebug.info(vm.medal);
});
vm.getUserMedals();
vm.buildPager();
};
/**
* buildPager
* pagination init
*/
vm.buildPager = function () {
vm.pagedItems = [];
vm.itemsPerPage = vm.itemsPerPageConfig.medalUsersListPerPage;
vm.currentPage = 1;
vm.figureOutItemsToDisplay();
};
/**
* figureOutItemsToDisplay
* @param callback
*/
vm.figureOutItemsToDisplay = function (callback) {
vm.resultMsg = 'MEDALS.USERS_IS_LOADING';
vm.getMedalUsers(vm.currentPage, function (items) {
mtDebug.info(items);
vm.filterLength = items.total;
vm.pagedItems = items.rows;
if (vm.pagedItems.length === 0) {
vm.resultMsg = 'MEDALS.USERS_IS_EMPTY';
} else {
vm.resultMsg = undefined;
}
if (callback) callback();
});
};
/**
* pageChanged
*/
vm.pageChanged = function () {
var element = angular.element('#top_of_medal_users_list');
vm.figureOutItemsToDisplay(function () {
$timeout(function () {
$('html,body').animate({scrollTop: element[0].offsetTop - 30}, 200);
}, 10);
});
};
/**
* getTraces
* @param p
* @param callback
*/
vm.getMedalUsers = function (p, callback) {
MedalsService.view({
medalName: $state.params.medalName,
skip: (p - 1) * vm.itemsPerPage,
limit: vm.itemsPerPage
}, function (res) {
callback(res);
});
};
/**
* inMyFollowing
* @returns {boolean}
*/
vm.inMyFollowing = function (u) {
return vm.user.following.indexOf(u._id) >= 0 ? true : false;
};
/**
* followTo
*/
vm.followTo = function (u) {
UsersService.userFollowTo({
userId: u._id
}).then(onSuccess)
.catch(onError);
function onSuccess(response) {
vm.user = Authentication.user = response;
$rootScope.$broadcast('user-follow-changed', response);
NotifycationService.showSuccessNotify('FOLLOW_SUCCESSFULLY');
}
function onError(response) {
NotifycationService.showErrorNotify($translate.instant(response.data.message, {name: u.displayName}), 'FOLLOW_ERROR');
}
};
/**
* unFollowTo
*/
vm.unFollowTo = function (u) {
UsersService.userUnfollowTo({
userId: u._id
}).then(onSuccess)
.catch(onError);
function onSuccess(response) {
vm.user = Authentication.user = response;
$rootScope.$broadcast('user-follow-changed', response);
NotifycationService.showSuccessNotify('UNFOLLOW_SUCCESSFULLY');
}
function onError(response) {
NotifycationService.showErrorNotify(response.data.message, 'UNFOLLOW_ERROR');
}
};
/**
* requestMedal
* @param md
*/
vm.requestMedal = function (md) {
var modalOptions = {
closeButtonText: $translate.instant('MEDALS.REQUEST_CONFIRM_CANCEL'),
actionButtonText: $translate.instant('MEDALS.REQUEST_CONFIRM_OK'),
headerText: $translate.instant('MEDALS.REQUEST_CONFIRM_HEADER_TEXT'),
bodyText: $translate.instant('MEDALS.REQUEST_CONFIRM_BODY_TEXT', {
score: md.score
})
};
ModalConfirmService.showModal({}, modalOptions)
.then(function (result) {
MedalsService.request({
medalName: md.name
}, function (res) {
successCallback(res);
}, function (err) {
errorCallback(err);
});
function successCallback(res) {
if ($state.current.name === 'medals.view') {
vm.filterLength += 1;
vm.currentPage = Math.ceil(vm.filterLength / vm.itemsPerPage);
vm.buildPager();
}
vm.userMedals.push(res);
NotifycationService.showSuccessNotify('MEDALS.REQUEST_SUCCESSFULLY');
}
function errorCallback(res) {
NotifycationService.showErrorNotify(res.data.message, 'MEDALS.REQUEST_ERROR');
}
});
};
}
}());

View File

@@ -0,0 +1,324 @@
@import (reference) "../../../core/client/less/mt-var.less";
.medals-side-overlay {
top: 50px !important;
}
/* csslint ignore:start */
.medal {
.medal-item {
width: 1.25em;
height: 1.25em;
font-size: 4em;
position: relative;
cursor: pointer;
display: inline-flex;
&:hover {
.medal-bg {
-webkit-text-stroke: 0.05em #fff;
}
}
&.owner {
.fa-check-circle {
display: block !important;
position: absolute;
font-size: 0.3em;
color: #006600;
top: 0.3em;
right: 0.3em;
text-shadow: 0 0 0.1em #fff, 0 0 0.1em #fff;
}
}
.medal-bg {
position: absolute;
margin: 0;
float: left;
//top: 0.5em;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
//filter: drop-shadow(5px 6px 5px rgba(153, 153, 153, 0.8));
//text-shadow: 0.1em 0.15em 0.5em #999, 0.01em 0.01em 0.1em #999;
text-shadow: 0.1em 0.1em 8px #999;
-webkit-text-stroke: 0.05em #e5e5e5;
&.dark-shadow {
//text-shadow: 0.1em 0.15em 0.5em #000, 0.01em 0.01em 0.1em #000 !important;
//text-shadow: 0.1em 0.1em 0.1em #2a2a2a, 0.1em 0.1em 0.1em #3a3a3a !important;
text-shadow: 0.1em 0.1em 8px #2a2a2a !important;
}
}
.medal-icon {
position: absolute;
margin: 0;
float: left;
left: 50%;
transform: translate(-50%, -50%);
}
.medal-header {
position: absolute;
margin: 0;
float: left;
left: 50%;
transform: translate(-50%, -50%);
}
.medal-footer {
position: absolute;
margin: 0;
float: left;
left: 50%;
transform: translate(-50%, -50%);
}
&.medal-xxxxxs {
transform: scale(0.2);
margin: -0.48em -0.48em;
}
&.medal-xxxxs {
transform: scale(0.3);
margin: -0.42em -0.42em;
}
&.medal-xxxs {
transform: scale(0.4);
margin: -0.36em -0.36em;
}
&.medal-xxs {
transform: scale(0.5);
margin: -0.3em -0.3em;
}
&.medal-xs {
transform: scale(0.6);
margin: -0.24em -0.24em;
}
&.medal-sm {
transform: scale(0.7);
margin: -0.18em -0.18em;
}
&.medal-md {
transform: scale(0.8);
margin: -0.12em -0.12em;
}
&.medal-lg {
transform: scale(0.9);
margin: -0.06em -0.06em;
}
&.medal-1x {
transform: scale(1.1);
margin: 0.06em 0.06em;
}
&.medal-2x {
transform: scale(1.2);
margin: 0.12em 0.12em;
}
&.medal-3x {
transform: scale(1.3);
margin: 0.18em 0.18em;
}
&.medal-4x {
transform: scale(1.4);
margin: 0.24em 0.24em;
}
&.medal-5x {
transform: scale(1.5);
margin: 0.3em 0.3em;
}
&.medal-6x {
transform: scale(1.6);
margin: 0.36em 0.36em;
}
&.medal-7x {
transform: scale(1.7);
margin: 0.42em 0.42em;
}
&.medal-8x {
transform: scale(1.8);
margin: 0.48em 0.48em;
}
&.medal-9x {
transform: scale(1.9);
margin: 0.54em 0.54em;
}
&.medal-10x {
transform: scale(2);
margin: 0.6em 0.6em;
}
&.medal-11x {
transform: scale(2.1);
margin: 0.66em 0.66em;
}
&.medal-12x {
transform: scale(2.2);
margin: 0.72em 0.72em;
}
&.medal-13x {
transform: scale(2.3);
margin: 0.78em 0.78em;
}
&.medal-14x {
transform: scale(2.4);
margin: 0.8em 0.8em;
}
&.medal-15x {
transform: scale(2.5);
margin: 0.86em 0.86em;
}
}
}
/* csslint ignore:end */
.medals-view-top {
.h3, h3 {
margin-top: 5px !important;
}
.medals-title {
color: #efefef;
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
}
.medals-data {
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
.fa, .far {
color: @mt-base-color !important;
}
}
.medal-overview {
font-size: 16px;
color: lighten(@gray-light, 20%);
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
}
}
.medals-list {
legend {
padding-bottom: 5px;
margin-bottom: 10px;
}
.medal-box {
padding: 10px 10px;
margin-bottom: 20px;
background-color: #4a4a4a;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
.medal-item {
.badge {
position: absolute;
top: 0.3em;
left: 0.3em;
box-shadow: 0 0 1px #fff;
}
}
.medal-info {
position: relative;
height: 100px;
text-align: right;
color: lighten(@gray-light, 20%);
float: right;
width: ~"calc(100% - 120px)";
text-shadow: 0 0 0.1em #2a2a2a,-0 -0 0.1em #2a2a2a;
p {
margin-bottom: 5px !important;
}
.desc {
font-size: 15px;
color: #f5f5f5;
}
.cmd {
position: absolute;
right: 0;
bottom: 0;
a {
&:last-child {
margin-left: 10px;
}
&:hover {
text-decoration: none;
color: @brand-info;
}
}
}
}
}
}
.medal-top-info {
color: lighten(@gray-light, 20%);
text-shadow: 0 0 0.1em #2a2a2a,-0 -0 0.1em #2a2a2a;
.desc {
font-size: 20px;
color: #f5f5f5;
}
.cmd {
margin-top: 10px;
a {
&:hover {
text-decoration: none;
color: @brand-info;
}
}
}
.info-item {
color: @mt-base-color;
}
}
.medal-users-list {
.user-item {
position: relative;
padding: 10px;
min-height: 94px;
margin: 10px 0;
border: solid 1px #3a3a3a;
background-color: #4a4a4a;
box-shadow: 2px 2px 5px rgba(32, 32, 32, 0.3);
a {
&:hover {
text-decoration: none;
color: @brand-info;
}
}
p {
margin: 0;
}
&:hover {
.btn-unfollow {
display: block;
}
}
.user-avatar {
float: left;
img {
width: 72px;
height: 72px;
}
}
.user-name {
margin-left: 10px;
font-size: 18px;
font-weight: 500;
}
.user-vip, .user-level {
margin-left: 10px;
}
.user-up-down {
font-size: 12px;
margin-left: 10px;
.torrent-up {
color: #33CC00;
}
.torrent-down {
color: #FF3300;
}
.up-data, .down-data {
color: lighten(@gray-base, 60%);
}
}
.btn-unfollow {
display: none;
position: absolute;
right: 10px;
top: 10px;
}
.add-time {
margin-left: 10px;
font-size: 12px;
color: #888;
}
}
}

View File

@@ -0,0 +1,9 @@
(function (app) {
'use strict';
app.registerModule('medals', ['core']);
app.registerModule('medals.admin', ['core.admin']);
app.registerModule('medals.admin.routes', ['core.admin.routes']);
app.registerModule('medals.services');
app.registerModule('medals.routes', ['ui.router', 'core.routes', 'medals.services']);
}(ApplicationConfiguration));

View File

@@ -0,0 +1,132 @@
(function () {
'use strict';
angular
.module('medals.services')
.factory('MedalsInfoServices', MedalsInfoServices);
MedalsInfoServices.$inject = ['MeanTorrentConfig', 'SafeColorsServices', '$filter'];
function MedalsInfoServices(MeanTorrentConfig, SafeColorsServices, $filter) {
var medalsConfig = MeanTorrentConfig.meanTorrentConfig.medals;
var service = {
getMedalsAll: getMedalsAll,
getMedalsSystemHelp: getMedalsSystemHelp,
getMedalsAdminHelp: getMedalsAdminHelp,
getMedalsSelfHelp: getMedalsSelfHelp,
mergeMedalsProperty: mergeMedalsProperty,
getMedal: getMedal
};
return service;
function getMedalsAll() {
var medals = $filter('where')(medalsConfig.type, {enable: true});
return {
items: fillMedalsProperty(medals),
types: $filter('groupBy')(medals, 'cats')
};
}
function getMedalsSystemHelp() {
var medals = $filter('where')(medalsConfig.type, {enable: true, passHelp: 'sys'});
return {
items: fillMedalsProperty(medals),
types: $filter('groupBy')(medals, 'cats')
};
}
function getMedalsAdminHelp() {
var medals = $filter('where')(medalsConfig.type, {enable: true, passHelp: 'admin'});
return {
items: fillMedalsProperty(medals),
types: $filter('groupBy')(medals, 'cats')
};
}
function getMedalsSelfHelp() {
var medals = $filter('where')(medalsConfig.type, {enable: true, passHelp: 'self'});
return {
items: fillMedalsProperty(medals),
types: $filter('groupBy')(medals, 'cats')
};
}
function getMedal(mName) {
var medal = $filter('where')(medalsConfig.type, {enable: true, name: mName});
medal = fillMedalsProperty(medal);
return medal[0];
}
function mergeMedalsProperty(mds) {
var medals = $filter('where')(medalsConfig.type, {enable: true});
var arr = [];
mds.forEach(function (m) {
if (m.name) {
arr.push(m);
} else {
arr.push(Object.assign(m, medals.find(function (item) {
return item.name === m.medalName;
})));
}
});
arr = fillMedalsProperty(arr);
return arr;
}
/**
* fillMedalsProperty
* @param mds
* @returns {*}
*/
function fillMedalsProperty(mds) {
angular.forEach(mds, function (m) {
m.bgColor = SafeColorsServices.getSafeColor();
switch (m.cats) {
case 'workers':
m.iconTop = '1.15em';
m.iconSize = '0.35em';
m.textFooterBottom = '0.65em';
m.textFooterSize = '0.2em';
break;
case 'users':
m.iconTop = '1.4em';
m.iconSize = '0.35em';
m.textFooterBottom = '0.5em';
m.textFooterSize = '0.2em';
break;
case 'vip':
m.textHeaderTop = '1.02em';
m.textHeaderSize = '0.4em';
m.textFooterBottom = '0.9em';
m.textFooterSize = '0.2em';
break;
case 'commemorative':
m.textHeaderTop = '1em';
m.textHeaderSize = '0.5em';
m.textFooterBottom = '0.5em';
m.textFooterSize = '0.2em';
break;
case 'events':
m.textHeaderTop = '1.6em';
m.textHeaderSize = '0.3em';
m.textFooterBottom = '0.5em';
m.textFooterSize = '0.2em';
break;
default:
m.iconTop = '1.15em';
m.iconSize = '0.35em';
m.textFooterBottom = '0.65em';
m.textFooterSize = '0.2em';
}
});
return mds;
}
}
}());

View File

@@ -0,0 +1,67 @@
(function () {
'use strict';
// Users service used for communicating with the users REST endpoint
angular
.module('medals.services')
.factory('MedalsService', MedalsService);
MedalsService.$inject = ['$resource', 'CacheFactory'];
function MedalsService($resource, CacheFactory) {
var medalsCache = CacheFactory.get('medalsCache') || CacheFactory.createCache('medalsCache');
var removeCache = function (res) {
medalsCache.removeAll();
return res.resource;
};
var medal = $resource('/api/medals/:userId/:medalName', {
userId: '@userId',
medalName: '@medalName'
}, {
count: {
method: 'GET',
isArray: true
},
query: {
method: 'GET',
isArray: true,
cache: medalsCache
},
update: {
method: 'PUT',
interceptor: {response: removeCache}
},
save: {
method: 'POST',
interceptor: {response: removeCache}
},
remove: {
method: 'DELETE',
interceptor: {response: removeCache}
},
delete: {
method: 'DELETE',
interceptor: {response: removeCache}
},
view: {
method: 'GET',
url: '/api/medals/view/:medalName',
params: {
medalName: '@medalName'
},
cache: medalsCache
},
request: {
method: 'PUT',
url: '/api/medals/request/:medalName',
params: {
medalName: '@medalName'
},
interceptor: {response: removeCache}
}
});
return medal;
}
}());

View File

@@ -0,0 +1,72 @@
<section ng-controller="MedalsController as vm" ng-init="vm.getMedals(); vm.initTopBackground()">
<div class="backdrop attachment-scroll">
<div class="filter">
<div class="container medals-view-top">
<div class="row margin-bottom-10">
<div class="col-sm-12 medals-title">
<h3 class="margin-bottom-10" translate="MEDALS.MEDALS_TITLE"></h3>
</div>
<div class="col-sm-12">
<ul class="list-unstyled medals-data list-inline">
<li><i class="far fa-shield-alt"> {{'MEDALS.TYPES_COUNT' | translate}}: {{vm.medals.typesLength}}</i></li>
<li><i class="far fa-shield-check"> {{'MEDALS.MEDALS_OPENED_COUNT' | translate}}: {{vm.medals.items.length}}</i></li>
<li><i class="far fa-user-shield"> {{'MEDALS.MEDALS_AWARD_COUNT' | translate}}: {{vm.medals.itemCount}}</i></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="medal-overview" ng-bind-html="vm.getMedalOverviewContent()"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container padding-top-20 padding-bottom-20">
<div class="row">
<div class="col-sm-12">
<div class="medals-list">
<div class="" ng-repeat="(key,value) in vm.medals.types">
<legend class="h4" translate="{{'MEDALS.CATS.'+key.toUpperCase()}}"></legend>
<div class="row">
<div ng-repeat="mt in vm.medals.items | where: {cats: key}">
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="medal medal-box">
<div class="medal-item medal-6x" ng-class="{'owner': vm.hasMedal(mt)}">
<i class="{{mt.faClass}} medal-bg dark-shadow" style="color:{{mt.bgColor}};"></i>
<i class="fa-inverse {{mt.iconClass}} medal-icon" style="font-size: {{mt.iconSize}}; top: {{mt.iconTop}}"></i>
<span class="fa-inverse medal-header" style="font-size: {{mt.textHeaderSize}}; top: {{mt.textHeaderTop}}" ng-if="mt.hasHeader">
{{'MEDALS.HEADERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
<span class="fa-inverse medal-footer" style="font-size: {{mt.textFooterSize}}; bottom: {{mt.textFooterBottom}}" ng-if="mt.hasFooter">
{{'MEDALS.FOOTERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
<span class="badge badge_danger" ng-if="mt.count>0">{{mt.count}}</span>
<i class="fa-inverse far fa-check-circle" style="display: none;"></i>
</div>
<div class="medal-info">
<p class="desc" translate="{{'MEDALS.DESC.'+mt.prefix.toUpperCase()}}"></p>
<span translate="{{'MEDALS.PASSHELP.'+mt.passHelp.toUpperCase()}}" ng-class="{'text-mt': mt.passHelp=='self'}"></span>
<div ng-if="mt.score" ng-class="{'text-mt': mt.score}">
<span>{{'MEDALS.HELP_CONDITION' | translate}}: </span>
<span>{{'TABLE_FIELDS.SCORE' | translate}} </span>
<span>{{mt.score}}</span>
</div>
<div class="cmd">
<a ui-sref="medals.view({medalName: mt.name})" translate="MEDALS.CMD_LIST_USER"
ng-if="mt.cats!='workers' || vm.medalsConfig.showWorkerUsersListToAll || vm.user.isOper"></a>
<a ui-sref="{}" translate="MEDALS.CMD_REQUEST" ng-click="vm.requestMedal(mt)" ng-if="mt.passHelp=='self' && !vm.hasMedal(mt)"></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@@ -0,0 +1,115 @@
<section ng-controller="MedalsController as vm" ng-init="vm.getMedal(); vm.initTopBackground()">
<div class="backdrop attachment-scroll">
<div class="filter">
<div class="container medals-view-top">
<div class="row">
<div class="row-sm-height">
<div class="col-sm-3 col-md-4 col-sm-height text-xxs-center text-sm-right">
<div class="medal">
<div class="medal-item medal-13x">
<i class="{{vm.medal.faClass}} medal-bg dark-shadow" style="color:{{vm.medal.bgColor}};"></i>
<i class="fa-inverse {{vm.medal.iconClass}} medal-icon" style="font-size: {{vm.medal.iconSize}}; top: {{vm.medal.iconTop}}"></i>
<span class="fa-inverse medal-header" style="font-size: {{vm.medal.textHeaderSize}}; top: {{vm.medal.textHeaderTop}}"
ng-if="vm.medal.hasHeader">
{{'MEDALS.HEADERSTRING.'+vm.medal.prefix.toUpperCase() | translate}}
</span>
<span class="fa-inverse medal-footer"
style="font-size: {{vm.medal.textFooterSize}}; bottom: {{vm.medal.textFooterBottom}}" ng-if="vm.medal.hasFooter">
{{'MEDALS.FOOTERSTRING.'+vm.medal.prefix.toUpperCase() | translate}}
</span>
</div>
</div>
</div>
<div class="col-sm-8 col-md-7 col-sm-height col-sm-middle text-xxs-center text-sm-left">
<div class="medal-top-info">
<ul class="list-unstyled">
<li class="desc"><p translate="{{'MEDALS.DESC.'+vm.medal.prefix.toUpperCase()}}"></p></li>
<li class="info-item"><i class="far fa-hand-holding-box"></i>&emsp;<span
translate="{{'MEDALS.PASSHELP.'+vm.medal.passHelp.toUpperCase()}}"></span></li>
<li class="info-item" ng-if="vm.medal.score">
<i class="far fa-coins"></i>&emsp;<span>{{'MEDALS.HELP_CONDITION' | translate}}: </span>
<span>{{'TABLE_FIELDS.SCORE' | translate}} </span>
<span>{{vm.medal.score}}</span>
</li>
<li class="info-item"><i class="far fa-user-shield"></i>&emsp;<span>{{'MEDALS.OWNED_USERS' | translate}}: {{vm.medal.count}}</span></li>
<li class="cmd" ng-if="!vm.hasMedal(vm.medal)">
<a ui-sref="{}" translate="MEDALS.CMD_REQUEST" ng-click="vm.requestMedal(vm.medal)" ng-if="vm.medal.passHelp=='self'"></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="up_to_top_div" up-to-top="top_of_medal_users_list" offset="-30"></div>
<div class="container padding-top-20 padding-bottom-20" id="top_of_medal_users_list">
<div class="row">
<div class="col-sm-12">
<div class="pagination-div-top" ng-if="vm.filterLength>vm.itemsPerPage">
<div class="row">
<div class="col-sm-12">
<ul uib-pagination boundary-links="true" max-size="8" items-per-page="vm.itemsPerPage" total-items="vm.filterLength"
ng-model="vm.currentPage"
ng-change="vm.pageChanged()"
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>
</div>
</div>
<div class="row">
<div class="col-xs-12 text-center margin-right-50" ng-if="vm.resultMsg">
<div class="jumbotron">
<i class="fa fa-users fa-2x text-muted" aria-hidden="true"></i>
<h3>{{vm.resultMsg | translate}}</h3>
</div>
</div>
<div class="medal-users-list" ng-if="!vm.resultMsg">
<div ng-repeat="item in vm.pagedItems">
<div data-ng-if="$index != 0 && $index % 2 == 0" class="clearfix visible-sm-block "></div>
<div data-ng-if="$index != 0 && $index % 3 == 0" class="clearfix visible-md-block visible-lg-block"></div>
<div class="col-sm-6 col-md-4">
<div class="user-item" mt-scale-by-mouse="{scale: 1.1, duration: '.5s'}">
<span user-info="item.user" info-class="user-avatar" info-avatar></span>
<p><span user-info="item.user" info-class="user-name" info-name></span><span message-to="item.user" to-class="message-to-icon"></span></p>
<p class="margin-bottom-5"><span class="add-time">{{'MEDALS.AWARD_AT' | translate}}: {{item.createdAt | date: "yyyy-MM-dd HH:mm:ss"}}</span></p>
<span vip-flag="item.user" vip-class="user-vip"></span>
<span score-level-curr="item.user" class="user-level"></span>
<span class="user-ud-text">
<span up-down-flag="item.user" up-down-class="user-up-down"></span>
</span>
<a class="btn btn-success btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.followTo(item.user)"
ng-if="!vm.inMyFollowing(item.user) && item.user._id!=vm.user._id">
{{ 'STATUS_FIELD.BTN_FOLLOW' | translate}}
</a>
<a class="btn btn-success btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.unFollowTo(item.user)"
ng-if="vm.inMyFollowing(item.user) && item.user._id!=vm.user._id">
{{ 'STATUS_FIELD.BTN_UNFOLLOW' | translate}}
</a>
</div>
</div>
</div>
</div>
</div>
<div class="pagination-div-bottom" ng-if="vm.filterLength>vm.itemsPerPage">
<ul uib-pagination boundary-links="true" max-size="8" items-per-page="vm.itemsPerPage" total-items="vm.filterLength"
ng-model="vm.currentPage"
ng-change="vm.pageChanged()"
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>
</div>
</div>
</section>

View File

@@ -0,0 +1,14 @@
'use strict';
/**
* Module dependencies
*/
var path = require('path'),
config = require(path.resolve('./config/config'));
/**
* Module init function.
*/
module.exports = function (app, db) {
};

View File

@@ -0,0 +1,314 @@
'use strict';
/**
* Module dependencies
*/
var path = require('path'),
config = require(path.resolve('./config/config')),
mongoose = require('mongoose'),
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
moment = require('moment'),
Medal = mongoose.model('Medal'),
objectId = require('mongodb').ObjectId,
async = require('async'),
traceLogCreate = require(path.resolve('./config/lib/tracelog')).create,
history = require(path.resolve('./config/lib/history')),
scoreUpdate = require(path.resolve('./config/lib/score')).update;
var traceConfig = config.meanTorrentConfig.trace;
var historyConfig = config.meanTorrentConfig.history;
var medalsConfig = config.meanTorrentConfig.medals;
var scoreConfig = config.meanTorrentConfig.score;
var mtDebug = require(path.resolve('./config/lib/debug'));
/**
* getMedalsCount
* @param req
* @param res
*/
exports.getMedalsCount = function (req, res) {
var medalName = undefined;
if (req.query.mName !== undefined) {
medalName = req.query.mName;
Medal.count({medalName: medalName}, function (err, count) {
res.json([{
_id: medalName,
count: count
}]);
});
} else {
Medal.aggregate([{
$group: {
_id: '$medalName',
count: {$sum: 1}
}
}]).exec(function (err, counts) {
res.json(counts);
});
}
};
/**
* viewMedal
* @param req
* @param res
*/
exports.viewMedal = function (req, res) {
var medalsAll = medalsConfig.type;
var medal = undefined;
medalsAll.forEach(function (md) {
if (md.name === req.params.medalName) {
medal = md;
}
});
if (medal.cats !== 'workers' || medalsConfig.showWorkerUsersListToAll || req.user.isOper) {
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 countQuery = function (callback) {
Medal.count({
medalName: req.params.medalName
}, function (err, count) {
if (err) {
callback(err, null);
} else {
callback(null, count);
}
});
};
var findQuery = function (callback) {
Medal.find({
medalName: req.params.medalName
}).populate('user', 'username displayName profileImageURL isVip score uploaded downloaded')
.skip(skip)
.limit(limit)
.sort('createdAt')
.exec(function (err, medals) {
if (err) {
callback(err, null);
} else {
callback(null, medals);
}
});
};
async.parallel([countQuery, findQuery], function (err, results) {
if (err) {
mtDebug.debugRed(err);
return res.status(422).send(err);
} else {
res.json({rows: results[1], total: results[0]});
}
});
} else {
return res.status(403).json({
message: 'ERROR: User is not authorized'
});
}
};
/**
* requestMedal
* @param req
* @param res
*/
exports.requestMedal = function (req, res) {
var user = req.user;
var medalsAll = medalsConfig.type;
var medal = undefined;
medalsAll.forEach(function (md) {
if (md.name === req.params.medalName) {
medal = md;
}
});
if (medal.passHelp === 'self') {
Medal.count({
user: objectId(user._id),
medalName: req.params.medalName
}, function (err, count) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else if (count > 0) {
return res.status(422).json({
message: 'SERVER.USER_ALREADY_HAS_THIS_MEDAL'
});
} else {
if (!medal.score || user.score >= medal.score) {
var newMedal = new Medal({
user: user,
medalName: req.params.medalName,
addBy: user
});
newMedal.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(newMedal);
//score update
var act = scoreConfig.action.scoreToRequestMedal;
act.params = {
medalDesc: 'MEDALS.DESC.' + medal.prefix.toUpperCase()
};
scoreUpdate(req, user, act, -(medal.score));
}
});
} else {
return res.status(422).send({
message: 'SERVER.SCORE_NOT_ENOUGH'
});
}
}
});
} else {
return res.status(403).json({
message: 'ERROR: User is not authorized'
});
}
};
/**
* getUserMedals
* @param req
* @param res
*/
exports.getUserMedals = function (req, res) {
Medal.find({
user: objectId(req.params.userId)
})
.sort('createdAt')
.exec(function (err, medals) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(medals);
}
});
};
/**
* addToUser
* @param req
* @param res
*/
exports.addToUser = function (req, res) {
var user = req.model;
if (user._id.equals(req.user._id) || req.user.isOper) {
Medal.count({
user: objectId(user._id),
medalName: req.params.medalName
}, function (err, count) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else if (count > 0) {
return res.status(422).json({
message: 'SERVER.USER_ALREADY_HAS_THIS_MEDAL'
});
} else {
var medal = new Medal({
user: user,
medalName: req.params.medalName,
addBy: req.user
});
medal.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(medal);
//create trace log
traceLogCreate(req, traceConfig.action.adminAddUserMedal, {
user: user._id,
medalName: req.params.medalName
});
// write history
history.insert(user._id, historyConfig.action.adminAddUserMedal, {
medalName: req.params.medalName,
by: req.user._id
});
}
});
}
});
} else {
return res.status(403).json({
message: 'ERROR: User is not authorized'
});
}
};
/**
* removeFromUser
* @param req
* @param res
*/
exports.removeFromUser = function (req, res) {
var user = req.model;
if (user._id.equals(req.user._id) || req.user.isOper) {
Medal.findOne({
user: objectId(user._id),
medalName: req.params.medalName
}, function (err, medal) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else if (!medal) {
return res.status(422).json({
message: 'SERVER.USER_HAS_NOT_THIS_MEDAL'
});
} else {
medal.remove(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(medal);
//create trace log
traceLogCreate(req, traceConfig.action.adminRemoveUserMedal, {
user: user._id,
medalName: req.params.medalName
});
// write history
history.insert(user._id, historyConfig.action.adminRemoveUserMedal, {
medalName: req.params.medalName,
by: req.user._id
});
}
});
}
});
} else {
return res.status(403).json({
message: 'ERROR: User is not authorized'
});
}
};

View File

@@ -0,0 +1,35 @@
'use strict';
/**
* Module dependencies
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Medal Schema
*/
var MedalSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
medalName: {
type: String,
trim: true,
default: ''
},
addBy: {
type: Schema.Types.ObjectId,
ref: 'User'
},
createdAt: {
type: Date,
default: Date.now
}
}, {usePushEach: true});
MedalSchema.index({user: 1});
MedalSchema.index({medalName: 1});
mongoose.model('Medal', MedalSchema);

View File

@@ -0,0 +1,62 @@
'use strict';
/**
* Module dependencies
*/
var acl = require('acl');
// Using the memory backend
acl = new acl(new acl.memoryBackend());
/**
* Invoke Torrents Permissions
*/
exports.invokeRolesPolicies = function () {
acl.allow(
[
{
roles: ['admin', 'oper'],
allows: [
{resources: '/api/medals', permissions: '*'},
{resources: '/api/medals/view/:medalName', permissions: '*'},
{resources: '/api/medals/request/:medalName', permissions: '*'},
{resources: '/api/medals/:userId', permissions: '*'},
{resources: '/api/medals/:userId/:medalName', permissions: '*'}
]
},
{
roles: ['user'],
allows: [
{resources: '/api/medals', permissions: ['get']},
{resources: '/api/medals/view/:medalName', permissions: ['get']},
{resources: '/api/medals/request/:medalName', permissions: ['put']},
{resources: '/api/medals/:userId', permissions: ['get']}
]
}
]
);
};
/**
* Check If Articles Policy Allows
*/
exports.isAllowed = function (req, res, next) {
var roles = (req.user) ? req.user.roles : ['guest'];
// Check for user roles
acl.areAnyRolesAllowed(roles, req.route.path, req.method.toLowerCase(), function (err, isAllowed) {
if (err) {
// An authorization error occurred
return res.status(500).send('Unexpected authorization error');
} else {
if (isAllowed) {
// Access granted! Invoke next middleware
return next();
} else {
return res.status(403).json({
message: 'User is not authorized'
});
}
}
});
};

View File

@@ -0,0 +1,26 @@
'use strict';
/**
* Module dependencies
*/
var medals = require('../controllers/medals.server.controller'),
medalsPolicy = require('../policies/medals.server.policy');
module.exports = function (app) {
app.route('/api/medals').all(medalsPolicy.isAllowed)
.get(medals.getMedalsCount);
app.route('/api/medals/view/:medalName').all(medalsPolicy.isAllowed)
.get(medals.viewMedal);
app.route('/api/medals/request/:medalName').all(medalsPolicy.isAllowed)
.put(medals.requestMedal);
app.route('/api/medals/:userId').all(medalsPolicy.isAllowed)
.get(medals.getUserMedals);
app.route('/api/medals/:userId/:medalName').all(medalsPolicy.isAllowed)
.put(medals.addToUser)
.delete(medals.removeFromUser);
};

View File

@@ -73,7 +73,7 @@
<div>
<dt class="h-line"></dt>
<dd class="h-line">
<button type="submit" class="btn btn-success btn-width-100">{{ 'MESSAGES_SEND_BUTTON' | translate }}</button>
<button type="submit" class="btn btn-success btn-min-width-100">{{ 'MESSAGES_SEND_BUTTON' | translate }}</button>
</dd>
</div>
</dl>
@@ -108,7 +108,7 @@
</thead>
<tbody>
<tr class="message-item" ng-repeat="m in vm.adminMessages">
<td class="col-md-8 width-400">
<td class="col-md-8 min-width-400">
<div class="message-title-admin text-long">
<span class="h4" ng-bind="m.title"></span>
<span class="badge badge_danger" ng-if="m.mustRead">
@@ -123,16 +123,16 @@
info-name></span> {{'MESSAGES_FIELD.INFO_SEND_AT' | translate}} {{m.createdat | date: 'yyyy-MM-dd HH:mm:ss' }}
</p>
</td>
<td class="col-md-1 td-v-middle text-center width-70">
<td class="col-md-1 td-v-middle text-center min-width-70">
<span ng-class="vm.getMessageClass(m);">{{m._readers.length}}</span>
</td>
<td class="col-md-2 td-v-middle text-center width-140">
<td class="col-md-2 td-v-middle text-center min-width-140">
<span ng-class="vm.getMessageClass(m);">{{'MESSAGE_TYPE_' + m.type.toUpperCase() | translate}}</span>
</td>
<!--<td class="col-md-1 td-v-middle text-center width-80">-->
<!--<span ng-class="vm.getMessageClass(m);">{{m.createdat | life}}</span>-->
<!--</td>-->
<td class="col-md-1 td-v-middle text-center width-70">
<td class="col-md-1 td-v-middle text-center min-width-70">
<input type="checkbox" class="tcheckbox" ng-model="vm.selected[m._id]"
id="checkbox_{{m._id}}">
</label>
@@ -144,7 +144,7 @@
<div class="margin-top-20" ng-if="vm.adminMessages.length">
<div class="pull-right margin-top-20">
<button class="btn btn-success btn-width-100" ng-click="vm.deleteSelected()">{{ 'BUTTON_MESSAGE_DELETE' | translate }}</button>
<button class="btn btn-success btn-min-width-100" ng-click="vm.deleteSelected()">{{ 'BUTTON_MESSAGE_DELETE' | translate }}</button>
</div>
</div>
</div>

View File

@@ -70,7 +70,7 @@
</td>
</tr>
<tr class="message-item" ng-if="!vm.resultMsg" ng-repeat="m in vm.pagedItems" ng-click="vm.showMessage($event, m);">
<td class="width-400">
<td class="min-width-400">
<img class="message-avatar" ng-src="{{m.from_user.profileImageURL}}" ng-if="m.type=='user'">
<span class="message-avatar glyphicon glyphicon-cog server-message-avatar" ng-if="m.type=='server'"></span>
<i class="fa fa-envelope message-avatar server-message-avatar" ng-if="m.type!='user' && m.type!='server'"></i>
@@ -122,7 +122,7 @@
next-text="{{ 'PAGE_TEXT_NEXT' | translate}}" last-text="{{ 'PAGE_TEXT_LAST' | translate}}">
</ul>
<div class="pull-right margin-top-20">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-if="vm.messageType=='user' || vm.messageType=='server'"
ng-click="vm.deleteSelected()">{{ 'BUTTON_MESSAGE_DELETE' | translate }}
</button>
@@ -190,11 +190,11 @@
emoji-dropup></textarea>
</div>
<div>
<button class="btn btn-default btn-width-100" ng-click="vm.hideMessage();">{{ 'BUTTON_MESSAGE_CLOSE' | translate }}</button>
<button class="btn btn-default btn-width-100" ng-click="vm.delete(vm.selectedMessage);"
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideMessage();">{{ 'BUTTON_MESSAGE_CLOSE' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.delete(vm.selectedMessage);"
ng-if="vm.selectedMessage.type=='user'">{{ 'BUTTON_MESSAGE_DELETE' | translate }}
</button>
<button class="btn btn-success btn-width-100 pull-right" ng-disabled="!vm.replyContent"
<button class="btn btn-success btn-min-width-100 pull-right" ng-disabled="!vm.replyContent"
ng-click="vm.replyMessage(vm.selectedMessage);"
ng-if="vm.selectedMessage.type=='user'">{{ 'BUTTON_MESSAGE_REPLY' | translate }}
</button>

View File

@@ -61,7 +61,7 @@
<div>
<dt class="h-line"></dt>
<dd class="h-line">
<button type="submit" class="btn btn-success btn-width-100">{{ 'MESSAGES_SEND_BUTTON' | translate }}</button>
<button type="submit" class="btn btn-success btn-min-width-100">{{ 'MESSAGES_SEND_BUTTON' | translate }}</button>
</dd>
</div>
</dl>

View File

@@ -245,10 +245,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(m.desc);
e.$options.hideable = true;

View File

@@ -3,20 +3,20 @@
<div class="container">
<div class="requests-btn-list padding-top-30 padding-bottom-30 text-center">
<div class="btn-group requests-group">
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.list">
{{'REQUESTS.NAV_LIST' | translate}}
</a>
<a class="btn btn-success btn-width-170"
<a class="btn btn-success btn-min-width-170"
ui-sref="requests.add">
{{'REQUESTS.NAV_ADD' | translate}}
</a>
<div class="clearfix visible-xxs-block "></div>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.my">
{{'REQUESTS.NAV_MY' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.res">
{{'REQUESTS.NAV_RES' | translate}}
</a>

View File

@@ -3,20 +3,20 @@
<div class="container">
<div class="requests-btn-list padding-top-30 padding-bottom-30 text-center">
<div class="btn-group requests-group">
<a class="btn btn-success btn-width-170"
<a class="btn btn-success btn-min-width-170"
ui-sref="requests.list">
{{'REQUESTS.NAV_LIST' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.add">
{{'REQUESTS.NAV_ADD' | translate}}
</a>
<div class="clearfix visible-xxs-block "></div>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.my">
{{'REQUESTS.NAV_MY' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.res">
{{'REQUESTS.NAV_RES' | translate}}
</a>

View File

@@ -3,20 +3,20 @@
<div class="container">
<div class="requests-btn-list padding-top-30 padding-bottom-30 text-center">
<div class="btn-group requests-group">
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.list">
{{'REQUESTS.NAV_LIST' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.add">
{{'REQUESTS.NAV_ADD' | translate}}
</a>
<div class="clearfix visible-xxs-block "></div>
<a class="btn btn-success btn-width-170"
<a class="btn btn-success btn-min-width-170"
ui-sref="requests.my">
{{'REQUESTS.NAV_MY' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.res">
{{'REQUESTS.NAV_RES' | translate}}
</a>

View File

@@ -3,20 +3,20 @@
<div class="container">
<div class="requests-btn-list padding-top-30 padding-bottom-30 text-center">
<div class="btn-group requests-group">
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.list">
{{'REQUESTS.NAV_LIST' | translate}}
</a>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.add">
{{'REQUESTS.NAV_ADD' | translate}}
</a>
<div class="clearfix visible-xxs-block "></div>
<a class="btn btn-default btn-width-170"
<a class="btn btn-default btn-min-width-170"
ui-sref="requests.my">
{{'REQUESTS.NAV_MY' | translate}}
</a>
<a class="btn btn-success btn-width-170"
<a class="btn btn-success btn-min-width-170"
ui-sref="requests.res">
{{'REQUESTS.NAV_RES' | translate}}
</a>

View File

@@ -3,20 +3,20 @@
<div class="container">
<div class="padding-top-30 padding-bottom-30 text-center">
<div class="btn-group requests-group">
<a class="btn btn-default btn-width-180"
<a class="btn btn-default btn-min-width-180"
ui-sref="requests.list">
{{'REQUESTS.NAV_LIST' | translate}}
</a>
<a class="btn btn-default btn-width-180"
<a class="btn btn-default btn-min-width-180"
ui-sref="requests.add">
{{'REQUESTS.NAV_ADD' | translate}}
</a>
<div class="clearfix visible-xxs-block "></div>
<a class="btn btn-default btn-width-180"
<a class="btn btn-default btn-min-width-180"
ui-sref="requests.my">
{{'REQUESTS.NAV_MY' | translate}}
</a>
<a class="btn btn-default btn-width-180"
<a class="btn btn-default btn-min-width-180"
ui-sref="requests.res">
{{'REQUESTS.NAV_RES' | translate}}
</a>
@@ -75,8 +75,8 @@
</div>
</h4>
</td>
<td class="col-md-1 td-v-middle text-center width-80">{{'MENU_TORRENTS_SUB.'+vm.request.type.toUpperCase() | translate}}</td>
<td class="col-md-1 td-v-middle text-center width-80">
<td class="col-md-1 td-v-middle text-center min-width-80">{{'MENU_TORRENTS_SUB.'+vm.request.type.toUpperCase() | translate}}</td>
<td class="col-md-1 td-v-middle text-center min-width-80">
{{vm.request.createdAt | life }}
<div>
<span class="badge badge_danger"
@@ -84,14 +84,14 @@
<span class="badge badge_success" ng-if="vm.request.accept">Finished</span>
</div>
</td>
<td class="col-md-1 td-v-middle text-center width-80">{{vm.request.rewards}}</td>
<td class="col-md-1 td-v-middle text-center width-60">
<td class="col-md-1 td-v-middle text-center min-width-80">{{vm.request.rewards}}</td>
<td class="col-md-1 td-v-middle text-center min-width-60">
<a href="#" ng-click="vm.scrollToElement('#top_of_responses');">{{vm.request.torrents.length}}</a>
</td>
<td class="col-md-1 td-v-middle text-center width-60">
<td class="col-md-1 td-v-middle text-center min-width-60">
<a href="#" ng-click="vm.scrollToElement('#top_of_comments');">{{vm.request.comments.length}}</a>
</td>
<td class="col-md-1 td-v-middle text-center width-80">
<td class="col-md-1 td-v-middle text-center min-width-80">
<span user-info="vm.request.user" info-name></span>
</td>
</tr>
@@ -108,22 +108,22 @@
<fieldset ng-disabled="vm.request.accept || vm.isExpired(vm.request);">
<a ui-sref="torrents.uploads({reqId: vm.request._id})"
ng-if="!vm.isCurrentUserOwner()"
class="btn btn-success btn-width-100">
class="btn btn-success btn-min-width-100">
{{ 'DO_UPLOAD' | translate}}
</a>
<button class="btn btn-default btn-width-100"
<button class="btn btn-default btn-min-width-100"
ng-if="vm.isCurrentUserOwner() || vm.user.isOper"
ng-click="vm.beginEditMakerDesc(vm.request)">
{{ 'REQUESTS.BTN_EDIT_DESC' | translate}}
</button>
</fieldset>
<button class="btn btn-default btn-width-100"
<button class="btn btn-default btn-min-width-100"
ng-disabled="vm.request.accept"
ng-if="vm.isCurrentUserOwner() || vm.user.isOper"
ng-click="vm.removeRequest();">
{{ 'BTN_REMOVE' | translate}}
</button>
<btn class="btn btn-default btn-width-100"
<btn class="btn btn-default btn-min-width-100"
ng-click="vm.scrollToElement('#top_of_new_comment');">
{{ 'REQUESTS.BTN_COMMENT' | translate}}
</btn>
@@ -304,7 +304,7 @@
</a>
</div>
<div class="col-sm-6 text-right">
<button class="btn btn-warning btn-width-80" translate="SUBMIT_CANCEL"
<button class="btn btn-warning btn-min-width-80" translate="SUBMIT_CANCEL"
ng-click="vm.submitInit();"></button>
<button class="btn btn-success"
translate="{{vm.comment.action == 'reply' ? 'SUBMIT_REPLY' : 'SUBMIT_COMMENT'}}"

View File

@@ -19,7 +19,7 @@
</div>
<div class="panel-footer" ng-class="vm.showFooter ? 'show-footer' : 'hide-footer'">
<div class="text-right">
<button class="btn btn-success btn-width-100" ng-disabled="!vm.contentChanged"
<button class="btn btn-success btn-min-width-100" ng-disabled="!vm.contentChanged"
ng-click="vm.saveConfigFileContent()">{{'BUTTON_SAVE' | translate}}
</button>
</div>

View File

@@ -6,7 +6,7 @@
<ul class="list-group commands-list">
<li class="list-group-item" id="{{cmd.eid}}" ng-repeat="cmd in vm.shellCommandConfig">
<div>
<button class="btn btn-sm btn-success btn-width-100" ng-disabled="vm.shellIsRunning"
<button class="btn btn-sm btn-success btn-min-width-100" ng-disabled="vm.shellIsRunning"
ng-click="vm.runCommand(cmd.command, cmd.eid)">
<i class="fa fa-spinner fa-spin"
ng-if="vm.shellIsRunning && vm.runningId==cmd.eid"></i> {{'SYSTEMS.BTN_RUN_COMMAND' | translate}}
@@ -19,7 +19,7 @@
<div class="cmd-desc">{{'SYSTEMS.CUSTOM_COMMAND' | translate}}</div>
<div>
<input type="text" class="form-control cmd-name" ng-model="vm.customCommand" ng-keydown="vm.commandKeydown($event)">
<button class="btn btn-sm btn-success btn-width-100 margin-top-10" ng-disabled="vm.shellIsRunning"
<button class="btn btn-sm btn-success btn-min-width-100 margin-top-10" ng-disabled="vm.shellIsRunning"
ng-click="vm.runCommand(vm.customCommand, 'command-custom')">
<i class="fa fa-spinner fa-spin"
ng-if="vm.shellIsRunning && vm.runningId=='command-custom'"></i> {{'SYSTEMS.BTN_RUN_COMMAND' | translate}}

View File

@@ -19,7 +19,7 @@
</div>
<div class="panel-footer" ng-class="vm.showFooter ? 'show-footer' : 'hide-footer'">
<div class="text-right">
<button class="btn btn-success btn-width-100" ng-disabled="!vm.contentChanged"
<button class="btn btn-success btn-min-width-100" ng-disabled="!vm.contentChanged"
ng-click="vm.saveConfigFileContent()">{{'BUTTON_SAVE' | translate}}
</button>
</div>

View File

@@ -19,7 +19,7 @@
</div>
<div class="panel-footer" ng-class="vm.showFooter ? 'show-footer' : 'hide-footer'">
<div class="text-right">
<button class="btn btn-success btn-width-100" ng-disabled="!vm.contentChanged"
<button class="btn btn-success btn-min-width-100" ng-disabled="!vm.contentChanged"
ng-click="vm.saveConfigFileContent()">{{'BUTTON_SAVE' | translate}}
</button>
</div>

View File

@@ -20,7 +20,7 @@
</div>
<div class="panel-footer" ng-class="vm.showFooter ? 'show-footer' : 'hide-footer'">
<div class="text-right">
<button class="btn btn-success btn-width-100" ng-disabled="!vm.contentChanged"
<button class="btn btn-success btn-min-width-100" ng-disabled="!vm.contentChanged"
ng-click="vm.saveConfigFileContent()">{{'BUTTON_SAVE' | translate}}
</button>
</div>

View File

@@ -19,7 +19,7 @@
</div>
<div class="panel-footer" ng-class="vm.showFooter ? 'show-footer' : 'hide-footer'">
<div class="text-right">
<button class="btn btn-success btn-width-100" ng-disabled="!vm.contentChanged"
<button class="btn btn-success btn-min-width-100" ng-disabled="!vm.contentChanged"
ng-click="vm.saveConfigFileContent()">{{'BUTTON_SAVE' | translate}}
</button>
</div>

View File

@@ -320,10 +320,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(t.content);
e.$options.hideable = true;
@@ -417,10 +417,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(r.content);
e.$options.hideable = true;

View File

@@ -42,8 +42,8 @@
</div>
</td>
<td class="col-md-1 td-v-middle text-center">{{item.replies ? item.replies.length : 0}}</td>
<td class="col-md-1 td-v-middle text-center width-100">{{item.createdAt | life}}</td>
<td class="col-md-1 td-v-middle text-center width-100">
<td class="col-md-1 td-v-middle text-center min-width-100">{{item.createdAt | life}}</td>
<td class="col-md-1 td-v-middle text-center min-width-100">
<span ng-if="item.updatedAt">
{{item.updatedAt | life}}
</span>
@@ -56,7 +56,7 @@
<span class="badge badge_default"
ng-if="item.status=='solved'"> {{item.status}} </span>
</td>
<td class="col-md-2 td-v-middle text-center width-150">
<td class="col-md-2 td-v-middle text-center min-width-150">
<span user-info="item.handler" info-name></span>
</td>
</tr>

View File

@@ -35,7 +35,7 @@
</thead>
<tbody>
<tr class="ticket-item" ng-repeat="item in vm.pagedItems">
<td class="col-md-2 td-v-middle width-150">
<td class="col-md-2 td-v-middle min-width-150">
<span user-info="item.from" info-class="ticket-avatar" info-avatar></span>
<span user-info="item.from" info-name></span>
</td>
@@ -45,8 +45,8 @@
</div>
</td>
<td class="col-md-1 td-v-middle text-center">{{item._replies ? item._replies.length : 0}}</td>
<td class="col-md-1 td-v-middle text-center width-100">{{item.createdAt | date:'MM-dd HH:mm'}}</td>
<td class="col-md-1 td-v-middle text-center width-100">
<td class="col-md-1 td-v-middle text-center min-width-100">{{item.createdAt | date:'MM-dd HH:mm'}}</td>
<td class="col-md-1 td-v-middle text-center min-width-100">
<span ng-if="item.updatedAt">
{{item.updatedAt | date:'MM-dd HH:mm'}}
</span>
@@ -59,7 +59,7 @@
<span class="badge badge_default"
ng-if="item.status=='solved'"> {{item.status}} </span>
</td>
<td class="col-md-1 td-v-middle text-center width-120">
<td class="col-md-1 td-v-middle text-center min-width-120">
<span user-info="item.handler" ng-if="item.handler" info-name></span>
<a class="btn btn-success" ng-if="!item.handler" ng-click="vm.handleTicket(item)">{{'SUPPORT.LINK_HANDLE' | translate}}</a>
</td>

View File

@@ -42,9 +42,9 @@
ng-bind-html="vm.getTicketContent(vm.ticket)">
</div>
<div class="ticket-buttons text-right" ng-if="vm.ticket.status!='solved'">
<a class="btn btn-sm btn-width-100" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
<a class="btn btn-sm btn-min-width-100" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
ng-if="!vm.ticket.handler" ng-click="vm.handleTicket(vm.ticket)">{{'SUPPORT.LINK_HANDLE' | translate}}</a>
<a class="btn btn-sm btn-width-100" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
<a class="btn btn-sm btn-min-width-100" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
ng-if="vm.ticket.status!='solved'" ng-click="vm.solvedTicket(vm.ticket)">{{'SUPPORT.LINK_SOLVED' | translate}}</a>
</div>
</div>
@@ -130,7 +130,7 @@
{{ 'MARKDOWN_LINK' | translate }}
</a>
</div>
<button type="submit" class="btn btn-success btn-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_REPLY' | translate}}
<button type="submit" class="btn btn-success btn-min-width-100 pull-right">{{'FORUMS.BTN_SUBMIT_REPLY' | translate}}
</button>
</form>
</div>

View File

@@ -1544,10 +1544,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(r.resource_detail_info.overview);
e.$options.hideable = true;

View File

@@ -36,10 +36,10 @@
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-width-100"
<button type="button" class="btn btn-default btn-min-width-100"
data-ng-click="modalOptions.close()">{{modalOptions.closeButtonText}}
</button>
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
data-ng-click="modalOptions.ok({reason: optionSelected.value, custom: optionSelected.custom});">{{modalOptions.actionButtonText}}
</button>
</div>

View File

@@ -25,22 +25,22 @@
</thead>
<tbody>
<tr ng-repeat="m in vm.uploadMakerList">
<td class="col-md-2 td-v-middle width-120">
<td class="col-md-2 td-v-middle min-width-120">
<span maker-info="m"></span>
</td>
<td class="col-md-2 td-v-middle width-120">
<td class="col-md-2 td-v-middle min-width-120">
<span user-info="m.user" info-name></span>
</td>
<td class="col-md-1 td-v-middle width-80 text-center">
<td class="col-md-1 td-v-middle min-width-80 text-center">
{{m.members.length}}
</td>
<td class="col-md-1 td-v-middle width-80 text-center">
<td class="col-md-1 td-v-middle min-width-80 text-center">
{{m.torrent_count}}
</td>
<td class="col-md-4 td-v-middle width-150">
<td class="col-md-4 td-v-middle min-width-150">
<span class="torrent-votes"><kbd>{{vm.TGI.getVoteTitle()}}</kbd> {{m.vote_average | number : 1}} / {{m.vote_count}} {{ 'TMDB_FIELDS.VOTE_UNIT' | translate}}</span>
</td>
<td class="col-md-2 td-v-middle width-120">
<td class="col-md-2 td-v-middle min-width-120">
<select class="form-control" ng-model="m.upload_access" ng-change="vm.onUploaderMakerAccessChanged(m);">
<option value="review">{{'UPLOADER.FIELDS_REVIEW' | translate}}
</option>
@@ -80,25 +80,25 @@
</thead>
<tbody>
<tr ng-repeat="u in vm.pagedItems">
<td class="col-md-1 td-v-middle width-50">
<td class="col-md-1 td-v-middle min-width-50">
<img class="ranking-user-img" title="{{u.displayName}}" ng-src="{{u.profileImageURL}}">
</td>
<td class="col-md-2 td-v-middle width-120">
<td class="col-md-2 td-v-middle min-width-120">
<span user-info="u" info-name></span>
<span vip-flag="u"></span>
</td>
<td class="col-md-1 td-v-middle width-100">
<td class="col-md-1 td-v-middle min-width-100">
<span score-level-curr="u"></span>
</td>
<td class="col-md-4 td-v-middle width-200">
<td class="col-md-4 td-v-middle min-width-200">
<span class="maker-list" ng-repeat="m in u.makers">
<span maker-info="m"></span>
</span>
</td>
<td class="col-md-2 td-v-middle width-80 text-center">
<td class="col-md-2 td-v-middle min-width-80 text-center">
{{u.uptotal}}
</td>
<td class="col-md-2 td-v-middle width-120">
<td class="col-md-2 td-v-middle min-width-120">
<select class="form-control" ng-model="u.upload_access" ng-change="vm.onUploaderUserAccessChanged(u);">
<option value="review">{{'UPLOADER.FIELDS_REVIEW' | translate}}
</option>

View File

@@ -177,11 +177,11 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.search.sid"
ng-click="vm.onSelectResult()">{{ 'BTN_SELECT' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideSearchPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideSearchPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
@@ -522,7 +522,7 @@
ng-model="vm.inputedEpisodes" ng-disabled="vm.inputedEpisodesOK" required>
</div>
<div class="col-sm-4 col-md-3 margin-left-20">
<button type="submit" class="btn btn-success btn-width-80">{{'BTN_CONTINUE' | translate}}</button>
<button type="submit" class="btn btn-success btn-min-width-80">{{'BTN_CONTINUE' | translate}}</button>
</div>
<div class="col-xs-12" ng-messages="vm.episodesForm.inputedEpisodes.$error" role="alert">
<p class="help-block error-text"
@@ -886,7 +886,7 @@
</div>
</div>
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 text-center">
<button class="uploaded_popup_close btn btn-success btn-width-100">{{'BUTTON_UPLOADED_POPUP_CLOSE' | translate}}</button>
<button class="uploaded_popup_close btn btn-success btn-min-width-100">{{'BUTTON_UPLOADED_POPUP_CLOSE' | translate}}</button>
</div>
</div>
</div>

View File

@@ -242,7 +242,7 @@
ng-click="vm.beginSaveScreenshots()">
{{'SAVE_THIS_SCREENSHOTS' | translate}}
</button>
<button class="btn btn-xs btn-mt-o margin-top-15 btn-width-80" mouse-enter-toggle-class="btn-mt-o-success"
<button class="btn btn-xs btn-mt-o margin-top-15 btn-min-width-80" mouse-enter-toggle-class="btn-mt-o-success"
base-class="btn-mt-o-primary"
ng-if="vm.isEditScreenshots && (vm.isOwner(vm.torrentLocalInfo) || vm.user.isOper)"
ng-click="vm.CancelScreenshots()">
@@ -449,15 +449,15 @@
</div>
<div class="img_nav text-center">
<span class="img_page_info"></span>
<button class="btn btn-bold btn-width-120 btn-mt-o popup_img_preview_close" mouse-enter-toggle-class="btn-mt-o-light"
<button class="btn btn-bold btn-min-width-120 btn-mt-o popup_img_preview_close" mouse-enter-toggle-class="btn-mt-o-light"
base-class="btn-mt-o-success">
{{'BUTTON_MESSAGE_CLOSE' | translate}}
</button>
<button class="btn btn-bold btn-width-120 btn-mt-o" mouse-enter-toggle-class="btn-mt-o-light" base-class="btn-mt-o-primary"
<button class="btn btn-bold btn-min-width-120 btn-mt-o" mouse-enter-toggle-class="btn-mt-o-light" base-class="btn-mt-o-primary"
ng-click="vm.previousImage()">
{{'PAGE_TEXT_PREVIOUS' | translate}}
</button>
<button class="btn btn-bold btn-width-120 btn-mt-o" mouse-enter-toggle-class="btn-mt-o-light" base-class="btn-mt-o-primary"
<button class="btn btn-bold btn-min-width-120 btn-mt-o" mouse-enter-toggle-class="btn-mt-o-light" base-class="btn-mt-o-primary"
ng-click="vm.nextImage()">
{{'PAGE_TEXT_NEXT' | translate}}
</button>
@@ -471,7 +471,7 @@
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-10 col-md-offset-1">
<div class="page-header"><h3>{{ 'ATTRIBUTE_TAGS' | translate}}</h3></div>
<div class="page-header"><h4>{{ 'ATTRIBUTE_TAGS' | translate}}</h4></div>
<dl class="dl-horizontal">
<div ng-repeat="item in vm.resourcesTags.radio | filter:vm.torrentLocalInfo.torrent_type">
<dt class="h-line">{{ 'RESOURCESTAGS.'+item.name+'.SELF' | translate}}:</dt>
@@ -507,10 +507,10 @@
<div style="margin-top: 20px;">
<dt class="h-line"></dt>
<dd class="h-line">
<button class="btn btn-success btn-width-100" ng-click="vm.setTorrentTags();">
<button class="btn btn-success btn-min-width-100" ng-click="vm.setTorrentTags();">
{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideTagsPopup();">
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideTagsPopup();">
{{ 'BUTTON_CANCEL' | translate }}
</button>
</dd>
@@ -563,11 +563,11 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.collection.name || !vm.collection.overview"
ng-click="vm.saveCollection();">{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideCollectionPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideCollectionPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
@@ -607,11 +607,11 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.collectionTorrent.cid"
ng-click="vm.saveInsertCollection();">{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideCollectionInsertPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideCollectionInsertPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
@@ -649,11 +649,11 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.album.name || !vm.album.overview"
ng-click="vm.saveAlbum();">{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideAlbumPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideAlbumPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
@@ -698,11 +698,11 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.albumTorrent.aid"
ng-click="vm.saveInsertAlbum();">{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideAlbumInsertPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideAlbumInsertPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
@@ -884,7 +884,7 @@
ng-click="vm.updateTorrentNfo()">
{{'SAVE_THIS_MEDIA_INFO' | translate}}
</button>
<button class="btn btn-xs margin-top-15 btn-width-80" mouse-enter-toggle-class="btn-mt-o-success"
<button class="btn btn-xs margin-top-15 btn-min-width-80" mouse-enter-toggle-class="btn-mt-o-success"
base-class="btn-mt-o-primary"
ng-if="vm.isOwner(vm.torrentLocalInfo) || vm.user.isOper"
ng-click="vm.CancelTorrentNfo()">
@@ -898,7 +898,7 @@
<dt class="h-line"></dt>
<dd class="h-line">
<div class="down-torrent">
<button class="btn btn-success btn-width-100" ng-click="vm.DLS.downloadTorrent(vm.torrentLocalInfo._id)"
<button class="btn btn-success btn-min-width-100" ng-click="vm.DLS.downloadTorrent(vm.torrentLocalInfo._id)"
translate="DOWNLOAD_TORRENT"></button>
<span torrent-file-link-button="vm.torrentLocalInfo" torrent-user="vm.user" info-class="btn-default"></span>
</div>
@@ -1007,7 +1007,7 @@
ng-click="vm.beginSaveScreenshots()">
{{'SAVE_THIS_SCREENSHOTS' | translate}}
</button>
<button class="btn btn-xs btn-mt-o margin-top-15 btn-width-80" mouse-enter-toggle-class="btn-mt-o-success"
<button class="btn btn-xs btn-mt-o margin-top-15 btn-min-width-80" mouse-enter-toggle-class="btn-mt-o-success"
base-class="btn-mt-o-primary"
ng-if="vm.isEditScreenshots && (vm.isOwner(vm.torrentLocalInfo) || vm.user.isOper)"
ng-click="vm.CancelScreenshots()">

View File

@@ -1891,7 +1891,7 @@ exports.list = function (req, res) {
]);
if (limit === 0) {
let i = query._pipeline.length;
var i = query._pipeline.length;
while (i--) {
if (Object.keys(query._pipeline[i])[0] === '$limit') {
query._pipeline.splice(i, 1);

View File

@@ -1,7 +1,6 @@
<section class="container" ng-controller="TracesController as vm" ng-init="vm.buildPager();">
<div class="row margin-top-20">
<div class="col-sm-12 traces-list">
<div class="row margin-bottom-20">
<div class="col-sm-8 col-md-9">
<h4>{{'ADMIN_TRACES_LIST' | translate}}</h4>
@@ -50,7 +49,7 @@
<!--<span message-to="m.user" to-class="message-to-icon"></span>-->
</td>
<td class="td-v-middle width-400"><json-tree object="m.content"></json-tree></td>
<td class="td-v-middle min-width-400"><json-tree object="m.content"></json-tree></td>
<td class="td-v-middle text-center">{{m.content.action}}</td>

View File

@@ -40,6 +40,13 @@
faClass: 'text-mt'
});
menuService.addSubMenuItem('mt-user', 'status', {
title: 'MENU_TORRENTS_STATUS',
state: 'status.torrents.uploaded',
faIcon: 'fa-hand-holding-seedling',
faClass: 'text-mt'
});
menuService.addSubMenuItem('mt-user', 'score', {
title: 'MENU_SCORE_LEVEL',
state: 'score.detail',

View File

@@ -124,7 +124,7 @@
.state('status', {
abstract: true,
url: '/status',
templateUrl: '/modules/users/client/views/status/status.client.view.html',
template: '<ui-view/>',
data: {
roles: ['user', 'oper', 'admin']
}
@@ -136,28 +136,35 @@
pageTitle: 'PAGETITLE.STATUS_ACCOUNT'
}
})
.state('status.uploaded', {
.state('status.torrents', {
url: '/torrents',
templateUrl: '/modules/users/client/views/status/torrents.client.view.html',
data: {
pageTitle: 'PAGETITLE.STATUS_TORRENTS'
}
})
.state('status.torrents.uploaded', {
url: '/uploaded',
templateUrl: '/modules/users/client/views/status/uploaded.client.view.html',
data: {
pageTitle: 'PAGETITLE.STATUS_UPLOADED'
}
})
.state('status.seeding', {
.state('status.torrents.seeding', {
url: '/seeding',
templateUrl: '/modules/users/client/views/status/seeding.client.view.html',
data: {
pageTitle: 'PAGETITLE.STATUS_SEEDING'
}
})
.state('status.downloading', {
.state('status.torrents.downloading', {
url: '/downloading',
templateUrl: '/modules/users/client/views/status/downloading.client.view.html',
data: {
pageTitle: 'PAGETITLE.STATUS_DOWNLOADING'
}
})
.state('status.warning', {
.state('status.torrents.warning', {
url: '/warning',
templateUrl: '/modules/users/client/views/status/warning.client.view.html',
data: {

View File

@@ -7,11 +7,11 @@
UserController.$inject = ['$scope', '$state', '$window', 'Authentication', 'userResolve', 'Notification', 'NotifycationService', 'MeanTorrentConfig',
'AdminService', 'ScoreLevelService', 'DebugConsoleService', 'TorrentGetInfoServices', 'SideOverlay', 'MakerGroupService', '$filter', '$translate',
'marked', 'ModalConfirmService'];
'marked', 'ModalConfirmService', 'MedalsService', 'MedalsInfoServices', 'localStorageService'];
function UserController($scope, $state, $window, Authentication, user, Notification, NotifycationService, MeanTorrentConfig,
AdminService, ScoreLevelService, mtDebug, TorrentGetInfoServices, SideOverlay, MakerGroupService, $filter, $translate,
marked, ModalConfirmService) {
marked, ModalConfirmService, MedalsService, MedalsInfoServices, localStorageService) {
var vm = this;
vm.TGI = TorrentGetInfoServices;
vm.authentication = Authentication;
@@ -30,10 +30,15 @@
vm.scoreLevelData = ScoreLevelService.getScoreLevelJson(vm.user.score);
vm.inputLengthConfig = MeanTorrentConfig.meanTorrentConfig.inputLength;
vm.inviteConfig = MeanTorrentConfig.meanTorrentConfig.invite;
vm.medalsConfig = MeanTorrentConfig.meanTorrentConfig.medals;
vm.homeConfig = MeanTorrentConfig.meanTorrentConfig.home;
vm.searchTags = [];
vm.maker = {};
angular.element(document).ready(function () {
});
vm.setUserScorePopover = {
title: 'SCORE_TITLE',
templateUrl: 'set-user-score.html',
@@ -64,6 +69,14 @@
mtDebug.info(vm.user);
/**
* initTopBackground
*/
vm.initTopBackground = function () {
var url = localStorageService.get('body_background_image') || vm.homeConfig.bodyBackgroundImage;
$('.backdrop').css('backgroundImage', 'url("' + url + '")');
};
/**
* $watch 'vm.user'
*/
@@ -536,5 +549,91 @@
var res = time + ' - ' + con;
return marked(res, {sanitize: false});
};
/**
* addMedal
* @param evt
*/
vm.addMedal = function (evt) {
SideOverlay.open(evt, 'medalsPopupSlide');
vm.medals = MedalsInfoServices.getMedalsAdminHelp();
};
/**
* hasMedal
* @param md
* @returns {boolean}
*/
vm.hasMedal = function (md) {
var has = false;
angular.forEach(vm.userMedals, function (m) {
if (m.medalName === md.name) {
has = true;
}
});
return has;
};
/**
* hideMedalsPopup
*/
vm.hideMedalsPopup = function () {
SideOverlay.close(null, 'medalsPopupSlide');
};
/**
* addMedalToUser
* @param md
*/
vm.addMedalToUser = function (md) {
if (vm.hasMedal(md)) {
MedalsService.remove({
userId: vm.user._id,
medalName: md.name
}, function (res) {
vm.removeMedalFromUserLocalMedals(res);
vm.getUserHistory();
NotifycationService.showSuccessNotify('MEDALS.REMOVE_SUCCESSFULLY');
}, function (res) {
NotifycationService.showErrorNotify(res.data.message, 'MEDALS.REMOVE_FAILED');
});
} else {
MedalsService.update({
userId: vm.user._id,
medalName: md.name
}, function (res) {
vm.userMedals.push(res);
vm.userMedals = MedalsInfoServices.mergeMedalsProperty(vm.userMedals);
vm.getUserHistory();
NotifycationService.showSuccessNotify('MEDALS.ADD_SUCCESSFULLY');
}, function (res) {
NotifycationService.showErrorNotify(res.data.message, 'MEDALS.ADD_FAILED');
});
}
};
/**
* removeMedalFromUserLocalMedals
* @param md
*/
vm.removeMedalFromUserLocalMedals = function (md) {
angular.forEach(vm.userMedals, function (m) {
if (m.medalName === md.medalName) {
vm.userMedals.splice(vm.userMedals.indexOf(m), 1);
}
});
};
/**
* getUserMedals
*/
vm.getUserMedals = function () {
MedalsService.query({
userId: vm.user._id
}, function (medals) {
vm.userMedals = MedalsInfoServices.mergeMedalsProperty(medals);
});
};
}
}());

View File

@@ -7,11 +7,11 @@
ScoreController.$inject = ['$rootScope', '$scope', '$state', '$translate', '$timeout', 'Authentication', '$window', 'ScoreLevelService', 'getStorageLangService',
'MeanTorrentConfig', 'ModalConfirmService', 'NotifycationService', 'InvitationsService', '$templateRequest', 'marked', '$filter', 'PeersService', 'moment',
'DebugConsoleService'];
'DebugConsoleService', 'localStorageService'];
function ScoreController($rootScope, $scope, $state, $translate, $timeout, Authentication, $window, ScoreLevelService, getStorageLangService, MeanTorrentConfig,
ModalConfirmService, NotifycationService, InvitationsService, $templateRequest, marked, $filter, PeersService, moment,
mtDebug) {
mtDebug, localStorageService) {
var vm = this;
vm.scoreConfig = MeanTorrentConfig.meanTorrentConfig.score;
vm.inviteConfig = MeanTorrentConfig.meanTorrentConfig.invite;
@@ -33,10 +33,19 @@
vm.examinationConfig = MeanTorrentConfig.meanTorrentConfig.examination;
vm.chatConfig = MeanTorrentConfig.meanTorrentConfig.chat;
vm.accessConfig = MeanTorrentConfig.meanTorrentConfig.access;
vm.homeConfig = MeanTorrentConfig.meanTorrentConfig.home;
vm.lang = getStorageLangService.getLang();
vm.user = Authentication.user;
/**
* initTopBackground
*/
vm.initTopBackground = function () {
var url = localStorageService.get('body_background_image') || vm.homeConfig.bodyBackgroundImage;
$('.backdrop').css('backgroundImage', 'url("' + url + '")');
};
/**
* auth-user-changed
*/

View File

@@ -92,10 +92,10 @@
var ele = $('#' + e.$editor.attr('id') + ' .md-footer');
angular.element(ele).addClass('text-right');
angular.element(ele[0].childNodes[0]).addClass('btn-width-80');
angular.element(ele[0].childNodes[0]).addClass('btn-min-width-80');
ele[0].childNodes[0].innerText = $translate.instant('FORUMS.BTN_SAVE');
var cbtn = angular.element('<button class="btn btn-default btn-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
var cbtn = angular.element('<button class="btn btn-default btn-min-width-80 margin-left-10">' + $translate.instant('FORUMS.BTN_CANCEL') + '</button>');
cbtn.bind('click', function (evt) {
e.setContent(vm.user.signature || $translate.instant('MAKER_NULL'));
e.$options.hideable = true;

View File

@@ -6,10 +6,10 @@
.controller('StatusController', StatusController);
StatusController.$inject = ['$scope', '$state', '$timeout', '$translate', 'Authentication', 'UsersService', 'ScoreLevelService', 'MeanTorrentConfig', 'ModalConfirmService',
'NotifycationService', 'moment'];
'NotifycationService', 'moment', 'localStorageService', 'MedalsService', 'MedalsInfoServices'];
function StatusController($scope, $state, $timeout, $translate, Authentication, UsersService, ScoreLevelService, MeanTorrentConfig, ModalConfirmService,
NotifycationService, moment) {
NotifycationService, moment, localStorageService, MedalsService, MedalsInfoServices) {
var vm = this;
vm.user = Authentication.user;
vm.scoreLevelData = ScoreLevelService.getScoreLevelJson(vm.user.score);
@@ -17,6 +17,25 @@
vm.signConfig = MeanTorrentConfig.meanTorrentConfig.sign;
vm.hnrConfig = MeanTorrentConfig.meanTorrentConfig.hitAndRun;
/**
* initTopBackground
*/
vm.initTopBackground = function () {
var url = localStorageService.get('body_background_image') || vm.homeConfig.bodyBackgroundImage;
$('.backdrop').css('backgroundImage', 'url("' + url + '")');
};
/**
* getMyMedals
*/
vm.getMyMedals = function () {
MedalsService.query({
userId: vm.user._id
}, function (medals) {
vm.userMedals = MedalsInfoServices.mergeMedalsProperty(medals);
});
};
/**
* unIdle
*/

View File

@@ -6,10 +6,10 @@
.controller('UserInfoController', UserInfoController);
UserInfoController.$inject = ['$scope', '$rootScope', '$state', 'Authentication', 'userResolve', 'ScoreLevelService', '$timeout', 'MeanTorrentConfig', 'UsersService',
'DebugConsoleService', 'NotifycationService'];
'DebugConsoleService', 'NotifycationService', 'localStorageService', 'MedalsService', 'MedalsInfoServices'];
function UserInfoController($scope, $rootScope, $state, Authentication, user, ScoreLevelService, $timeout, MeanTorrentConfig, UsersService,
mtDebug, NotifycationService) {
mtDebug, NotifycationService, localStorageService, MedalsService, MedalsInfoServices) {
var vm = this;
vm.authentication = Authentication;
@@ -20,9 +20,18 @@
vm.isContextUserSelf = isContextUserSelf;
vm.scoreLevelData = ScoreLevelService.getScoreLevelJson(vm.user.score);
vm.hnrConfig = MeanTorrentConfig.meanTorrentConfig.hitAndRun;
vm.homeConfig = MeanTorrentConfig.meanTorrentConfig.home;
mtDebug.info(user);
/**
* initTopBackground
*/
vm.initTopBackground = function () {
var url = localStorageService.get('body_background_image') || vm.homeConfig.bodyBackgroundImage;
$('.backdrop').css('backgroundImage', 'url("' + url + '")');
};
/**
* messageTo
*/
@@ -90,5 +99,16 @@
NotifycationService.showErrorNotify(response.data.message, 'UNFOLLOW_ERROR');
}
};
/**
* getUserMedals
*/
vm.getUserMedals = function () {
MedalsService.query({
userId: vm.user._id
}, function (medals) {
vm.userMedals = MedalsInfoServices.mergeMedalsProperty(medals);
});
};
}
}());

View File

@@ -0,0 +1,36 @@
(function () {
'use strict';
angular.module('users')
.directive('medalFlag', medalFlag);
medalFlag.$inject = ['$compile', '$translate', '$filter'];
function medalFlag($compile, $translate, $filter) {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
scope.$watch(attrs.medalFlag, function (s) {
if (s) {
var user = s;
var number = attrs.medalCount;
var title = $translate.instant('USER_MEDAL_FLAG', {name: user.displayName});
var cls = attrs.medalFlagClass;
var ele = angular.element('<i class="far fa-shield-alt text-mt" ng-click="$event.stopPropagation();"> <span class="medal-data">' + number + '</span></i>');
ele.addClass(cls ? cls : '');
ele.attr('title', title);
element.append(ele);
$compile(element.contents())(scope);
}
});
}
}
}());

View File

@@ -0,0 +1,35 @@
(function () {
'use strict';
angular.module('users')
.directive('ratioFlag', ratioFlag);
ratioFlag.$inject = ['$compile', '$translate', '$filter'];
function ratioFlag($compile, $translate, $filter) {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
scope.$watch(attrs.ratioFlag, function (s) {
if (s) {
var user = s;
var title = $translate.instant('USER_RATIO_FLAG', {name: user.displayName});
var cls = attrs.ratioFlagClass;
var ele = angular.element('<i class="fas fa-hands text-mt" ng-click="$event.stopPropagation();"> <span class="ratio-data">' + $filter('ratio')(user.ratio, 2) + '</span></i>');
ele.addClass(cls ? cls : '');
ele.attr('title', title);
element.append(ele);
$compile(element.contents())(scope);
}
});
}
}
}());

View File

@@ -0,0 +1,42 @@
@import (reference) "../../../core/client/less/mt-var.less";
.score-top {
color: #999;
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
.score-title {
color: #f5f5f5;
}
}
.score-progress {
height: 30px;
margin-bottom: 2px;
.progress-bar {
line-height: 30px;
}
}
.score-level-default {
cursor: pointer;
color: #333 !important;
> kbd {
font-size: 12px;
color: #333 !important;
background-color: #eee !important;
}
}
.score-level {
cursor: pointer;
color: #FF6600;
text-shadow: none;
> kbd {
font-size: 12px;
background-color: #FF6600;
}
}
.curr-score {
color: @mt-base-color;
font-size: 48px;
}

View File

@@ -5,27 +5,6 @@
border-bottom: solid 1px #eee;
}
.userinfo-header {
margin-bottom: 0;
.userinfo-col {
display: table;
span {
display: table-cell;
vertical-align: middle;
}
.userinfo-btn {
@media (max-width: @screen-xxs-max) {
display: table-row;
float: none !important;
line-height: 4;
.btn:not(:first-child) {
margin-left: 5px;
}
}
}
}
}
.mt-xxs-break-before {
@media (max-width: @screen-xxs-max) {
display: table-row !important;
@@ -39,10 +18,13 @@
resize: vertical;
}
}
.user-history {
height: 150px;
line-height: 1;
overflow-y: scroll;
p {
margin-bottom: 0;
}
}
.curr-score-info {
@@ -57,3 +39,69 @@
line-height: 1.8;
}
}
.medals-user-top {
.user-avatar {
float: left;
img {
width: 60px;
height: 60px;
}
}
.user-data {
margin-left: 70px;
color: #999;
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
.user-name {
margin-left: 10px;
color: #efefef;
text-shadow: 0 0 0.1em #000,-0 -0 0.1em #000;
&:hover {
color: @brand-primary;
text-decoration: none;
}
}
.user-vip, .user-level {
margin-left: 10px;
}
.user-up-down {
font-size: 12px;
margin-left: 10px;
.torrent-up {
color: #33CC00;
}
.torrent-down {
color: #FF3300;
}
.up-data, .down-data {
color: lighten(@gray-base, 60%);
}
}
.user-medals-count {
margin-left: 10px;
font-size: 12px;
.user-medal-flag {
.medal-data {
color: #999;
}
}
}
.user-ratio {
margin-left: 10px;
font-size: 12px;
.user-ratio-flag {
.ratio-data {
color: #999;
}
}
}
}
.user-medals-list {
text-align: center;
padding: 10px;
border-top: solid 2px #2a2a2a;
.medal {
display: inline;
}
}
}

View File

@@ -1,17 +1,62 @@
<section class="container">
<div class="page-header userinfo-header">
<div class="row">
<div class="col-xs-12 col-xs-offset-0 col-md-10 col-md-offset-1 userinfo-col">
<span class="h3" ng-bind="vm.user.displayName"></span>
<span class="pull-right margin-bottom-5 userinfo-btn">
<a class="btn btn-default btn-width-80" ng-click="vm.messageTo()" ng-if="!vm.isContextUserSelf()">
<section>
<div class="backdrop attachment-scroll" ng-init="vm.getUserMedals(); vm.initTopBackground()">
<div class="filter">
<div class="container medals-user-top">
<div class="row">
<div class="col-sm-12">
<span user-info="vm.user" info-class="user-avatar" info-avatar></span>
<ul class="list-unstyled user-data">
<li class="margin-bottom-10">
<span user-info="vm.user" info-class="h3 user-name" info-name></span>
<span message-to="vm.user" to-class="message-to-icon"></span>
</li>
<li>
<span vip-flag="vm.user" vip-class="user-vip"></span>
<span score-level-curr="vm.user" class="user-level"></span>
<span class="user-ud-text"><span up-down-flag="vm.user" up-down-class="user-up-down"></span></span>
<span class="user-ratio"><span ratio-flag="vm.user" ratio-flag-class="user-ratio-flag"></span></span>
<span class="user-medals-count"><span medal-flag="vm.user" medal-count="{{vm.userMedals.length}}" medal-flag-class="user-medal-flag"></span></span>
</li>
</ul>
</div>
</div>
<div class="row" ng-if="vm.userMedals && vm.userMedals.length>0">
<div class="col-sm-12">
<div class="user-medals-list margin-top-10">
<div class="medal">
<div class="medal-item medal-2x" ng-repeat="mt in vm.userMedals"
uib-tooltip="{{ 'MEDALS.DESC.'+mt.prefix.toUpperCase() | translate}}" tooltip-placement="top-center">
<i class="{{mt.faClass}} medal-bg dark-shadow" style="color:{{mt.bgColor}};"></i>
<i class="fa-inverse {{mt.iconClass}} medal-icon" style="font-size: {{mt.iconSize}}; top: {{mt.iconTop}}"></i>
<span class="fa-inverse medal-header" style="font-size: {{mt.textHeaderSize}}; top: {{mt.textHeaderTop}}" ng-if="mt.hasHeader">
{{'MEDALS.HEADERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
<span class="fa-inverse medal-footer" style="font-size: {{mt.textFooterSize}}; bottom: {{mt.textFooterBottom}}" ng-if="mt.hasFooter">
{{'MEDALS.FOOTERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="margin-top-20 text-right">
<a class="btn btn-min-width-100 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-click="vm.messageTo()" ng-if="!vm.isContextUserSelf()">
{{ 'STATUS_FIELD.BTN_SEND_MESSAGE' | translate}}
</a>
<a class="btn btn-default btn-width-80" ui-sref="dataCenter.score({uid: vm.user._id})"
ng-if="vm.authentication.user.isOper">
<a class="btn btn-min-width-100 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ui-sref="dataCenter.score({uid: vm.user._id})" ng-if="vm.authentication.user.isOper">
{{ 'STATUS_FIELD.BTN_VIEW_USER_DATA_CENTER' | translate}}
</a>
<button class="btn btn-primary" ng-if="vm.authentication.user.isAdmin"
<a class="btn btn-min-width-100 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-click="vm.addMedal($event)" ng-if="vm.authentication.user.isOper">
{{ 'STATUS_FIELD.BTN_ADD_MEDAL' | translate}}
</a>
<button class="btn btn-min-width-100 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-if="vm.authentication.user.isAdmin"
uib-popover-template="vm.presentInvitationsPopover.templateUrl"
popover-title="{{vm.presentInvitationsPopover.title | translate}}"
popover-trigger="'outsideClick'"
@@ -21,295 +66,298 @@
ng-click="vm.presentInvitationsPopover.numbers = 1; vm.presentInvitationsPopover.days = 1;">
{{'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}}-->
<!--</a>-->
<a class="btn btn-primary btn-width-80" ng-click="vm.remove()" ng-if="!vm.isContextUserSelf() && !vm.user.isOper">
<a class="btn btn-min-width-100 margin-top-5" mouse-enter-toggle-class="btn-default" base-class="btn-mt-o"
ng-click="vm.remove()" ng-if="!vm.isContextUserSelf() && !vm.user.isOper">
{{ 'STATUS_FIELD.BTN_REMOVE' | translate}}
</a>
</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-10 col-md-offset-1 admin-user-info">
<dl class="dl-horizontal dl-hover margin-top-20 margin-bottom-20">
<dt class="h-line">{{ 'STATUS_FIELD.PICTURE' | translate}}</dt>
<dd class="h-line">
<img class="status-avatar" ng-src="{{vm.user.profileImageURL}}">
<div class="pull-right" ng-if="vm.authentication.user.isOper && !vm.user.isAdmin">
<a href="#" ng-click="vm.resetDefaultProfileImage();">{{'STATUS_FIELD.RESET_DEFAULT_PICTURE' | translate}}</a>
</div>
</dd>
<dt class="h-line">ID</dt>
<dd class="h-line">
<mark>{{ vm.user._id }}</mark>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.USERNAME' | translate}}</dt>
<dd class="h-line">{{ vm.user.username }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.DISPLAY_NAME' | translate}}</dt>
<dd class="h-line">
{{ vm.user.displayName }}
<span vip-flag="vm.user"></span>
<div class="pull-right" ng-if="vm.authentication.user.isAdmin">
<button class="btn btn-default btn-xs btn-width-100"
ng-click="vm.addVIPMonths();">{{'STATUS_FIELD.ADD_VIP_MONTHS' | translate}}
</button>
<button class="btn btn-default btn-xs btn-width-100" ng-if="vm.user.isVip"
ng-click="vm.resetVIPData();">{{'STATUS_FIELD.RESET_VIP_DATA' | translate}}
</button>
</div>
</dd>
<div ng-if="vm.user.invited_by">
<dt class="h-line">{{ 'STATUS_FIELD.INVITED_BY' | translate}}</dt>
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<dl class="dl-horizontal dl-hover margin-top-20 margin-bottom-20">
<dt class="h-line">{{ 'STATUS_FIELD.PICTURE' | translate}}</dt>
<dd class="h-line">
<span user-info="vm.user.invited_by" info-name></span>
<!--<span message-to="vm.user.invited_by" to-class="message-to-icon"></span>-->
<img class="status-avatar" ng-src="{{vm.user.profileImageURL}}">
<div class="pull-right" ng-if="vm.authentication.user.isOper && !vm.user.isAdmin">
<a href="#" ng-click="vm.resetDefaultProfileImage();">{{'STATUS_FIELD.RESET_DEFAULT_PICTURE' | translate}}</a>
</div>
</dd>
</div>
<dt class="h-line">{{ 'STATUS_FIELD.EMAIL' | translate}}</dt>
<dd class="h-line">{{ vm.user.email }}</dd>
<div ng-if="vm.authentication.user.isOper">
<dt class="h-line">{{ 'STATUS_FIELD.PASSKEY' | translate}}</dt>
<dt class="h-line">ID</dt>
<dd class="h-line">
<mark>{{ vm.user.passkey }}</mark>
<mark>{{ vm.user._id }}</mark>
</dd>
</div>
<dt class="h-line">{{ 'STATUS_FIELD.ROLE' | translate}}</dt>
<dd class="h-line">
<mark>{{ vm.user.roles[0] }}</mark>
<div class="pull-right" ng-if="vm.authentication.user.username != vm.user.username && vm.authentication.user.isAdmin">
<select class="width-100" ng-model="vm.selectedRole" ng-change="vm.onUserRoleChanged();">
<option ng-repeat="r in vm.userRolesConfig" value="{{r}}">{{ r }}
</option>
</select>
<dt class="h-line">{{ 'STATUS_FIELD.USERNAME' | translate}}</dt>
<dd class="h-line">{{ vm.user.username }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.DISPLAY_NAME' | translate}}</dt>
<dd class="h-line">
{{ vm.user.displayName }}
<span vip-flag="vm.user"></span>
<div class="pull-right" ng-if="vm.authentication.user.isAdmin">
<button class="btn btn-default btn-xs btn-min-width-100"
ng-click="vm.addVIPMonths();">{{'STATUS_FIELD.ADD_VIP_MONTHS' | translate}}
</button>
<button class="btn btn-default btn-xs btn-min-width-100" ng-if="vm.user.isVip"
ng-click="vm.resetVIPData();">{{'STATUS_FIELD.RESET_VIP_DATA' | translate}}
</button>
</div>
</dd>
<div ng-if="vm.user.invited_by">
<dt class="h-line">{{ 'STATUS_FIELD.INVITED_BY' | translate}}</dt>
<dd class="h-line">
<span user-info="vm.user.invited_by" info-name></span>
<!--<span message-to="vm.user.invited_by" to-class="message-to-icon"></span>-->
</dd>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.MAKER' | translate}}</dt>
<dd class="h-line">
<dt class="h-line">{{ 'STATUS_FIELD.EMAIL' | translate}}</dt>
<dd class="h-line">{{ vm.user.email }}</dd>
<div ng-if="vm.authentication.user.isOper">
<dt class="h-line">{{ 'STATUS_FIELD.PASSKEY' | translate}}</dt>
<dd class="h-line">
<mark>{{ vm.user.passkey }}</mark>
</dd>
</div>
<dt class="h-line">{{ 'STATUS_FIELD.ROLE' | translate}}</dt>
<dd class="h-line">
<mark>{{ vm.user.roles[0] }}</mark>
<div class="pull-right" ng-if="vm.authentication.user.username != vm.user.username && vm.authentication.user.isAdmin">
<select class="min-width-100" ng-model="vm.selectedRole" ng-change="vm.onUserRoleChanged();">
<option ng-repeat="r in vm.userRolesConfig" value="{{r}}">{{ r }}
</option>
</select>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.MAKER' | translate}}</dt>
<dd class="h-line">
<span class="maker-list" ng-repeat="m in vm.user.makers">
<span maker-info="m"></span>
</span>
<span ng-if="vm.user.makers.length==0">-</span>
<span ng-if="vm.user.makers.length==0">-</span>
<div class="pull-right"
ng-if="vm.authentication.user.isOper && !vm.alreadyIsFounder(vm.user);">
<button class="btn btn-default btn-xs btn-width-100" ng-click="vm.showMakerGroup($event);">
{{'STATUS_FIELD.BTN_CREATE_MAKER' | translate}}
</button>
</div>
</dd>
<div class="pull-right"
ng-if="vm.authentication.user.isOper && !vm.alreadyIsFounder(vm.user);">
<button class="btn btn-default btn-xs btn-min-width-100" ng-click="vm.showMakerGroup($event);">
{{'STATUS_FIELD.BTN_CREATE_MAKER' | translate}}
</button>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.STATUS' | translate}}</dt>
<dd class="h-line">
<span ng-class="{'span-banned': vm.user.status != 'normal'}">{{ 'STATUS_FIELD.' + vm.user.status.toUpperCase() | translate }}</span>
<dt class="h-line">{{ 'STATUS_FIELD.STATUS' | translate}}</dt>
<dd class="h-line">
<span ng-class="{'span-banned': vm.user.status != 'normal'}">{{ 'STATUS_FIELD.' + vm.user.status.toUpperCase() | translate }}</span>
<div class="pull-right"
ng-if="vm.authentication.user.username != vm.user.username && vm.authentication.user.isOper && !vm.user.isAdmin">
<select class="width-100" ng-model="vm.selectedStatus" ng-change="vm.onUserStatusChanged();">
<option ng-repeat="r in vm.userStatusConfig.value" value="{{r.value}}">{{ 'STATUS_FIELD.' + r.name | translate }}
</option>
</select>
</div>
</dd>
<div class="pull-right"
ng-if="vm.authentication.user.username != vm.user.username && vm.authentication.user.isOper && !vm.user.isAdmin">
<select class="min-width-100" ng-model="vm.selectedStatus" ng-change="vm.onUserStatusChanged();">
<option ng-repeat="r in vm.userStatusConfig.value" value="{{r.value}}">{{ 'STATUS_FIELD.' + r.name | translate }}
</option>
</select>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.SCORE' | translate}}</dt>
<dd class="h-line">
<span>{{ vm.user.score | number: 2 }}</span> <span score-level-curr="vm.user"></span>
<dt class="h-line">{{ 'STATUS_FIELD.SCORE' | translate}}</dt>
<dd class="h-line">
<span>{{ vm.user.score | number: 2 }}</span> <span score-level-curr="vm.user"></span>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-width-100"
uib-popover-template="vm.setUserScorePopover.templateUrl"
popover-title="{{vm.setUserScorePopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserScorePopover.isOpen"
popover-class="set-score-popover"
ng-click="vm.setUserScorePopover.number = undefined;">
+/-
</button>
</div>
</dd>
<li class="status-divider"></li>
<div ng-show="vm.user.isVip">
<dt class="h-line">{{ 'STATUS_FIELD.VIP_START_AT' | translate}}</dt>
<dd class="h-line">{{ vm.user.vip_start_at | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.VIP_END_AT' | translate}}</dt>
<dd class="h-line">{{ vm.user.vip_end_at | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-min-width-100"
uib-popover-template="vm.setUserScorePopover.templateUrl"
popover-title="{{vm.setUserScorePopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserScorePopover.isOpen"
popover-class="set-score-popover"
ng-click="vm.setUserScorePopover.number = undefined;">
+/-
</button>
</div>
</dd>
<li class="status-divider"></li>
</div>
<dt class="h-line">{{ 'STATUS_FIELD.SIGNUP_DATE' | translate}}</dt>
<dd class="h-line">{{ vm.user.created | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<div ng-show="vm.user.isVip">
<dt class="h-line">{{ 'STATUS_FIELD.VIP_START_AT' | translate}}</dt>
<dd class="h-line">{{ vm.user.vip_start_at | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.LATEST_SIGNED_TIME' | translate}}</dt>
<dd class="h-line">{{ vm.user.last_signed | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.VIP_END_AT' | translate}}</dt>
<dd class="h-line">{{ vm.user.vip_end_at | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.LATEST_REFRESH_TIME' | translate}}</dt>
<dd class="h-line">{{ vm.user.refreshat | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<li class="status-divider"></li>
</div>
<div ng-if="vm.authentication.user.isOper && !vm.user.isAdmin">
<dt class="h-line">{{ 'STATUS_FIELD.CURR_SIGNED_IP' | translate}}</dt>
<dd class="h-line">{{ vm.user.curr_signed_ip }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.SIGNUP_DATE' | translate}}</dt>
<dd class="h-line">{{ vm.user.created | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.CURR_LEECHED_IP' | translate}}</dt>
<dd class="h-line">{{ vm.user.curr_leeched_ip }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.LATEST_SIGNED_TIME' | translate}}</dt>
<dd class="h-line">{{ vm.user.last_signed | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.SIGNED_IP' | translate}}</dt>
<dt class="h-line">{{ 'STATUS_FIELD.LATEST_REFRESH_TIME' | translate}}</dt>
<dd class="h-line">{{ vm.user.refreshat | date: 'yyyy-MM-dd HH:mm:ss' }}</dd>
<div ng-if="vm.authentication.user.isOper && !vm.user.isAdmin">
<dt class="h-line">{{ 'STATUS_FIELD.CURR_SIGNED_IP' | translate}}</dt>
<dd class="h-line">{{ vm.user.curr_signed_ip }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.CURR_LEECHED_IP' | translate}}</dt>
<dd class="h-line">{{ vm.user.curr_leeched_ip }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.SIGNED_IP' | translate}}</dt>
<dd class="h-line">
<div class="list-all-ips">
<span class="ip-item" ng-repeat="t in vm.user.signed_ip">{{t}}</span>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.LEECHED_IP' | translate}}</dt>
<dd class="h-line">
<div class="list-all-ips">
<span class="ip-item" ng-repeat="t in vm.user.leeched_ip">{{t}}</span>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.BT_CLIENT' | translate}}</dt>
<dd class="h-line">
<div class="list-all-clients">
<span class="client-item" ng-repeat="t in vm.user.client_agent">{{t}}</span>
</div>
</dd>
</div>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.FOLLOWERS' | translate}}</dt>
<dd class="h-line">{{ vm.user.followers.length }}
<a class="pull-right" ui-sref="follow.userFollowers({userId: vm.user._id})"
ng-if="vm.user.followers.length>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.FOLLOWING' | translate}}</dt>
<dd class="h-line">{{ vm.user.following.length }}
<a class="pull-right" ui-sref="follow.userFollowing({userId: vm.user._id})"
ng-if="vm.user.following.length>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
</dd>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.UPLOADED' | translate}}</dt>
<dd class="h-line">
<div class="list-all-ips">
<span class="ip-item" ng-repeat="t in vm.user.signed_ip">{{t}}</span>
<span class="glyphicon glyphicon-arrow-up torrent-up"></span>
<span>{{ vm.user.uploaded | bytes:2 }}</span>
<span class="true_updown text-muted"
ng-if="vm.user.true_uploaded>0">|&emsp;{{ 'STATUS_FIELD.TRUE_UPLOADED' | translate}}{{ vm.user.true_uploaded | bytes:2 }}</span>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-min-width-100"
uib-popover-template="vm.setUserUploadedPopover.templateUrl"
popover-title="{{vm.setUserUploadedPopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserUploadedPopover.isOpen"
popover-class="set-uploaded-popover"
ng-click="vm.setUserUploadedPopover.number = undefined;">
+/-
</button>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.LEECHED_IP' | translate}}</dt>
<dt class="h-line">{{ 'STATUS_FIELD.DOWNLOADED' | translate}}</dt>
<dd class="h-line">
<div class="list-all-ips">
<span class="ip-item" ng-repeat="t in vm.user.leeched_ip">{{t}}</span>
<span class="glyphicon glyphicon-arrow-down torrent-down"></span>
<span>{{ vm.user.downloaded | bytes:2 }}</span>
<span class="true_updown text-muted"
ng-if="vm.user.true_downloaded>0">|&emsp;{{ 'STATUS_FIELD.TRUE_DOWNLOADED' | translate}}{{ vm.user.true_downloaded | bytes:2 }}</span>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-min-width-100"
uib-popover-template="vm.setUserDownloadedPopover.templateUrl"
popover-title="{{vm.setUserDownloadedPopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserDownloadedPopover.isOpen"
popover-class="set-downloaded-popover"
ng-click="vm.setUserDownloadedPopover.number = undefined;">
+/-
</button>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.BT_CLIENT' | translate}}</dt>
<dd class="h-line">
<div class="list-all-clients">
<span class="client-item" ng-repeat="t in vm.user.client_agent">{{t}}</span>
<dt class="h-line">{{ 'STATUS_FIELD.RATIO' | translate}}</dt>
<dd class="h-line"><span ng-class="vm.user.ratio == 0 ? 'ratio-warning' : 'ratio-normal' ">{{ vm.user.ratio | ratio}}</span></dd>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.UPTOTAL' | translate}}</dt>
<dd class="h-line">{{ vm.user.uptotal }} <a class="pull-right" ui-sref="admin.user-uplist({userId: vm.user._id})"
ng-if="vm.user.uptotal>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.SEEDED' | translate}}</dt>
<dd class="h-line">{{ vm.user.seeded }} <a class="pull-right" ui-sref="admin.user-seeding({userId: vm.user._id})"
ng-if="vm.user.seeded>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.LEECHED' | translate}}</dt>
<dd class="h-line">{{ vm.user.leeched }} <a class="pull-right" ui-sref="admin.user-leeching({userId: vm.user._id})"
ng-if="vm.user.leeched>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.FINISHED' | translate}}</dt>
<dd class="h-line">{{ vm.user.finished }}</dd>
<div ng-if="vm.user.hnr_warning>0 && vm.hnrConfig.enable">
<dt class="h-line">{{ 'STATUS_FIELD.HNR_WARNING' | translate}}</dt>
<dd class="h-line">
<span class="badge badge_danger">{{vm.user.hnr_warning}}</span>
<a class="pull-right" ui-sref="admin.user-warning({userId: vm.user._id})"
ng-if="vm.user.hnr_warning>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
</dd>
</div>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.FORUM_TOPICS' | translate}}</dt>
<dd class="h-line">{{ vm.user.topics }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.FORUM_REPLIES' | translate}}</dt>
<dd class="h-line">{{ vm.user.replies }}</dd>
<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">
<span ng-repeat="h in vm.historyList | orderBy: '-createdAt'" ng-bind-html="vm.getHistoryContent(h)"></span>
</div>
</dd>
</div>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.FOLLOWERS' | translate}}</dt>
<dd class="h-line">{{ vm.user.followers.length }}
<a class="pull-right" ui-sref="follow.userFollowers({userId: vm.user._id})"
ng-if="vm.user.followers.length>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.FOLLOWING' | translate}}</dt>
<dd class="h-line">{{ vm.user.following.length }}
<a class="pull-right" ui-sref="follow.userFollowing({userId: vm.user._id})"
ng-if="vm.user.following.length>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
</dd>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.UPLOADED' | translate}}</dt>
<dd class="h-line">
<span class="glyphicon glyphicon-arrow-up torrent-up"></span>
<span>{{ vm.user.uploaded | bytes:2 }}</span>
<span class="true_updown text-muted"
ng-if="vm.user.true_uploaded>0">|&emsp;{{ 'STATUS_FIELD.TRUE_UPLOADED' | translate}}{{ vm.user.true_uploaded | bytes:2 }}</span>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-width-100"
uib-popover-template="vm.setUserUploadedPopover.templateUrl"
popover-title="{{vm.setUserUploadedPopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserUploadedPopover.isOpen"
popover-class="set-uploaded-popover"
ng-click="vm.setUserUploadedPopover.number = undefined;">
+/-
</button>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.DOWNLOADED' | translate}}</dt>
<dd class="h-line">
<span class="glyphicon glyphicon-arrow-down torrent-down"></span>
<span>{{ vm.user.downloaded | bytes:2 }}</span>
<span class="true_updown text-muted"
ng-if="vm.user.true_downloaded>0">|&emsp;{{ 'STATUS_FIELD.TRUE_DOWNLOADED' | translate}}{{ vm.user.true_downloaded | bytes:2 }}</span>
<div class="pull-right" ng-if="vm.authentication.user.isOper">
<button class="btn btn-default btn-xs btn-width-100"
uib-popover-template="vm.setUserDownloadedPopover.templateUrl"
popover-title="{{vm.setUserDownloadedPopover.title | translate}}"
popover-trigger="'outsideClick'"
popover-placement="top-right"
popover-is-open="vm.setUserDownloadedPopover.isOpen"
popover-class="set-downloaded-popover"
ng-click="vm.setUserDownloadedPopover.number = undefined;">
+/-
</button>
</div>
</dd>
<dt class="h-line">{{ 'STATUS_FIELD.RATIO' | translate}}</dt>
<dd class="h-line"><span ng-class="vm.user.ratio == 0 ? 'ratio-warning' : 'ratio-normal' ">{{ vm.user.ratio | ratio}}</span></dd>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.UPTOTAL' | translate}}</dt>
<dd class="h-line">{{ vm.user.uptotal }} <a class="pull-right" ui-sref="admin.user-uplist({userId: vm.user._id})"
ng-if="vm.user.uptotal>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.SEEDED' | translate}}</dt>
<dd class="h-line">{{ vm.user.seeded }} <a class="pull-right" ui-sref="admin.user-seeding({userId: vm.user._id})"
ng-if="vm.user.seeded>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.LEECHED' | translate}}</dt>
<dd class="h-line">{{ vm.user.leeched }} <a class="pull-right" ui-sref="admin.user-leeching({userId: vm.user._id})"
ng-if="vm.user.leeched>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a></dd>
<dt class="h-line">{{ 'STATUS_FIELD.FINISHED' | translate}}</dt>
<dd class="h-line">{{ vm.user.finished }}</dd>
<div ng-if="vm.user.hnr_warning>0 && vm.hnrConfig.enable">
<dt class="h-line">{{ 'STATUS_FIELD.HNR_WARNING' | translate}}</dt>
<dt class="h-line">{{ 'STATUS_FIELD.ADMIN_REMARKS' | translate}}</dt>
<dd class="h-line">
<span class="badge badge_danger">{{vm.user.hnr_warning}}</span>
<a class="pull-right" ui-sref="admin.user-warning({userId: vm.user._id})"
ng-if="vm.user.hnr_warning>0">{{ 'STATUS_FIELD.DETAIL' | translate }}</a>
<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-min-width-100 margin-top-10"
ng-click="vm.saveRemarks()">
{{'STATUS_FIELD.BTN_SAVE_REMARKS' | translate}}
</button>
</div>
</dd>
</div>
<li class="status-divider"></li>
<dt class="h-line">{{ 'STATUS_FIELD.FORUM_TOPICS' | translate}}</dt>
<dd class="h-line">{{ vm.user.topics }}</dd>
<dt class="h-line">{{ 'STATUS_FIELD.FORUM_REPLIES' | translate}}</dt>
<dd class="h-line">{{ vm.user.replies }}</dd>
<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="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}}
</button>
</div>
</dd>
</dl>
</dl>
</div>
</div>
</div>
<!-- =================================================================
side-overlay create maker
================================================================== -->
<div id="makerSlide" side-overlay="right" side-class="maker-side-overlay" side-opened="vm.onPopupMessageOpen();" side-close-on-esc side-modal>
<div class="maker-popup">
<h4 translate="ABOUT.FORM_MAKER_FOR" translate-values="{name: vm.user.displayName}"></h4>
@@ -338,14 +386,61 @@
</div>
<div class="bottom-control">
<button class="btn btn-success btn-width-100"
<button class="btn btn-success btn-min-width-100"
ng-disabled="!vm.maker.name || !vm.maker.desc"
ng-click="vm.createMakerGroup();">{{ 'BUTTON_SAVE' | translate }}
</button>
<button class="btn btn-default btn-width-100" ng-click="vm.hideMakerPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideMakerPopup();">{{ 'BUTTON_CANCEL' | translate }}</button>
</div>
</div>
<!-- =================================================================
side-overlay add medal
================================================================== -->
<div id="medalsPopupSlide" side-overlay="top" side-class="medals-side-overlay" side-modal side-close-on-esc>
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="page-header"><h4 translate="MEDALS.SELECT_MEDAL_TO_USER" translate-values="{uname: vm.user.displayName}"></h4></div>
<dl class="dl-horizontal">
<div ng-repeat="(key,value) in vm.medals.types">
<dt class="h-line">{{'MEDALS.CATS.'+key.toUpperCase() | translate}}:</dt>
<dd>
<div class="medal">
<div class="medal-item" ng-repeat="mt in vm.medals.items | where: {cats: key}"
ng-click="vm.addMedalToUser(mt)" ng-class="{'owner': vm.hasMedal(mt)}"
uib-tooltip="{{ 'MEDALS.DESC.'+mt.prefix.toUpperCase() | translate}}" tooltip-placement="top-center">
<i class="{{mt.faClass}} medal-bg" style="color:{{mt.bgColor}};"></i>
<i class="fa-inverse {{mt.iconClass}} medal-icon" style="font-size: {{mt.iconSize}}; top: {{mt.iconTop}}"></i>
<span class="fa-inverse medal-header" style="font-size: {{mt.textHeaderSize}}; top: {{mt.textHeaderTop}}" ng-if="mt.hasHeader">
{{'MEDALS.HEADERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
<span class="fa-inverse medal-footer" style="font-size: {{mt.textFooterSize}}; bottom: {{mt.textFooterBottom}}" ng-if="mt.hasFooter">
{{'MEDALS.FOOTERSTRING.'+mt.prefix.toUpperCase() | translate}}
</span>
<i class="fa-inverse far fa-check-circle" style="display: none;"></i>
</div>
</div>
</dd>
</div>
<div class="margin-top-20">
<dt class="h-line"></dt>
<dd class="h-line">
<button class="btn btn-default btn-min-width-100" ng-click="vm.hideMedalsPopup();">
{{ 'BUTTON_CLOSE' | translate }}
</button>
</dd>
</div>
</dl>
</div>
</div>
</div>
</div>
<!-- =================================================================
template set-user-score
================================================================== -->
<script type="text/ng-template" id="set-user-score.html">
<form class="form-inline set-score-popover-form text-center">
<div class="form-group">
@@ -356,6 +451,9 @@
</form>
</script>
<!-- =================================================================
template set-user-uploaded
================================================================== -->
<script type="text/ng-template" id="set-user-uploaded.html">
<form class="form-inline set-uploaded-popover-form text-center">
<div class="form-group">
@@ -366,6 +464,9 @@
</form>
</script>
<!-- =================================================================
template set-user-downloaded
================================================================== -->
<script type="text/ng-template" id="set-user-downloaded.html">
<form class="form-inline set-downloaded-popover-form text-center">
<div class="form-group">
@@ -376,6 +477,9 @@
</form>
</script>
<!-- =================================================================
template present-invitations
================================================================== -->
<script type="text/ng-template" id="present-invitations.html">
<form class="set-invitations-popover">
<div class="form-group">

View File

@@ -27,7 +27,7 @@
</div>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-success btn-width-100">{{ 'SIGN.BTN_SIGN_IN' | translate}}</button>
<button type="submit" class="btn btn-success btn-min-width-100">{{ 'SIGN.BTN_SIGN_IN' | translate}}</button>
&nbsp; or&nbsp;
<a ui-sref="authentication.signup">{{ 'SIGN.BTN_SIGN_UP' | translate}}</a>
</div>

View File

@@ -61,7 +61,7 @@
style="color:white; white-space:nowrap;">{{requirementsProgress}}%</span></uib-progressbar>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-success btn-width-100"
<button type="submit" class="btn btn-success btn-min-width-100"
ng-disabled="vm.isSendingMail">{{ 'SIGN.BTN_SIGN_UP' | translate}}
</button>
&nbsp; or&nbsp;

View File

@@ -52,12 +52,12 @@
<span up-down-flag="item" up-down-class="follow-up-down"></span>
</span>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.followTo(item)"
ng-if="!vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_FOLLOW' | translate}}
</a>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.unFollowTo(item)"
ng-if="vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_UNFOLLOW' | translate}}

View File

@@ -52,7 +52,7 @@
<span up-down-flag="item" up-down-class="follow-up-down"></span>
</span>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.unFollowTo(item)">
{{ 'STATUS_FIELD.BTN_UNFOLLOW' | translate}}
</a>

View File

@@ -42,12 +42,12 @@
<span up-down-flag="item" up-down-class="follow-up-down"></span>
</span>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.followTo(item)"
ng-if="!vm.isContextUserSelf(item) && !vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_FOLLOW' | translate}}
</a>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.unFollowTo(item)"
ng-if="!vm.isContextUserSelf(item) && vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_UNFOLLOW' | translate}}

View File

@@ -42,12 +42,12 @@
<span up-down-flag="item" up-down-class="follow-up-down"></span>
</span>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.followTo(item)"
ng-if="!vm.isContextUserSelf(item) && !vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_FOLLOW' | translate}}
</a>
<a class="btn btn-default btn-sm btn-bold btn-width-80 btn-unfollow"
<a class="btn btn-default btn-sm btn-bold btn-min-width-80 btn-unfollow"
ng-click="vm.unFollowTo(item)"
ng-if="!vm.isContextUserSelf(item) && vm.inMyFollowing(item)">
{{ 'STATUS_FIELD.BTN_UNFOLLOW' | translate}}

View File

@@ -15,7 +15,7 @@
</div>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-success btn-width-100" ng-disabled="vm.isSendingMail">
<button type="submit" class="btn btn-success btn-min-width-100" ng-disabled="vm.isSendingMail">
<i class="fa fa-spinner fa-pulse" ng-show="vm.isSendingMail"></i> {{ 'SIGN.BTN_SUBMIT' | translate}}
</button>
</div>

View File

@@ -36,7 +36,7 @@
style="color:white; white-space:nowrap;">{{requirementsProgress}}%</span></uib-progressbar>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-success btn-width-100">{{ 'SIGN.BTN_UPDATE_PASSWORD' | translate}}</button>
<button type="submit" class="btn btn-success btn-min-width-100">{{ 'SIGN.BTN_UPDATE_PASSWORD' | translate}}</button>
</div>
</fieldset>
</form>

View File

@@ -1,75 +1,89 @@
<section ng-controller="ScoreController as vm" ng-init="vm.init();">
<div class="margin-top-40">
<div class="text-center">
<span>{{ 'SCORE.CURRENT_SCORE' | translate }}</span> <span class="curr-score">{{ vm.scoreLevelData.score | number: 2}}</span> <span
score-level-curr="vm.user"></span>
</div>
<div class="backdrop attachment-scroll" ng-init="vm.initTopBackground()">
<div class="filter">
<div class="container score-top">
<div class="row">
<div class="col-sm-12">
<div class="text-center">
<span class="h3 score-title">{{ 'SCORE.CURRENT_SCORE' | translate }}</span>&emsp;
<span class="curr-score">{{ vm.scoreLevelData.score | number: 2}}</span>&emsp;
<span score-level-curr="vm.user"></span>
</div>
<div class="row margin-top-30">
<div class="col-md-8 col-md-offset-2">
<div>
<span>{{ vm.scoreLevelData.currLevelValue | number: 2 }}</span>
<span class="pull-right">{{ vm.scoreLevelData.nextLevelValue | number: 2 }}</span>
</div>
<div class="progress score-progress">
<div class="progress-bar progress-bar-success" style="width: {{ vm.scoreLevelData.currPercentString }}">
<span>{{ vm.scoreLevelData.currPercentString }}</span>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div>
<span>{{ vm.scoreLevelData.currLevelValue | number: 2 }}</span>
<span class="pull-right">{{ vm.scoreLevelData.nextLevelValue | number: 2 }}</span>
</div>
<div class="progress score-progress">
<div class="progress-bar progress-bar-success" style="width: {{ vm.scoreLevelData.currPercentString }}">
<span>{{ vm.scoreLevelData.currPercentString }}</span>
</div>
</div>
<div>
<span class="score-level-default" score-level-curr="vm.user"></span>
<span class="score-level-default pull-right" score-level-next="vm.user"></span>
</div>
</div>
</div>
<div class="row margin-top-20" ng-show="vm.inviteConfig.openInvite">
<div class="col-md-10 col-md-offset-1 text-center">
<button class="btn" mouse-enter-toggle-class="btn-success" base-class="btn-mt-o"
ng-disabled="vm.user.score < vm.inviteConfig.scoreExchange"
translate="EXCHANGE_INVITATION" translate-values='{ score: vm.inviteConfig.scoreExchange}'
ng-click="vm.exchangeInvitation();">
</button>
</div>
</div>
<div class="row margin-top-20" ng-hide="vm.inviteConfig.openInvite">
<div class="col-md-10 col-md-offset-1 text-center">
<div class="alert alert-warning" role="alert">
<strong>{{ 'NOTE_CAPTION' | translate }}</strong> {{ 'INVITE_CLOSED' | translate }}
</div>
</div>
</div>
</div>
</div>
<div>
<span class="score-level-default" score-level-curr="vm.user"></span>
<span class="score-level-default pull-right" score-level-next="vm.user"></span>
</div>
</div>
</div>
<div class="container">
<div class="margin-top-40">
<div class="row margin-top-30" ng-init="vm.getMyPeers()">
<div class="col-md-10 col-md-offset-1 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.INCOME_ESTIMATE' | translate}}</legend>
<ul>
<li ng-bind-html="vm.getMarkedCurrDownloadingString()"></li>
<li ng-bind-html="vm.getMarkedCurrSeedingString()"></li>
<li ng-bind-html="vm.getMarkedVipStatusString()"></li>
<li ng-bind-html="vm.getMarkedCurrUpSpeedString()"></li>
<li ng-bind-html="vm.getMarkedCurrDownSpeedString()"></li>
</ul>
<div class="alert alert-warning">
<span ng-bind-html="vm.getMarkedCurrScoreString()"></span>
</div>
</div>
</div>
</div>
<div class="row margin-top-30" ng-show="vm.inviteConfig.openInvite">
<div class="col-md-8 col-md-offset-2 text-center">
<button class="btn btn-success" ng-disabled="vm.user.score < vm.inviteConfig.scoreExchange"
translate="EXCHANGE_INVITATION" translate-values='{ score: vm.inviteConfig.scoreExchange}'
ng-click="vm.exchangeInvitation();">
</button>
</div>
</div>
<div class="row margin-top-30" ng-hide="vm.inviteConfig.openInvite">
<div class="col-md-8 col-md-offset-2 text-center">
<div class="alert alert-warning" role="alert">
<strong>{{ 'NOTE_CAPTION' | translate }}</strong> {{ 'INVITE_CLOSED' | translate }}
<div class="row margin-top-30"
ng-init="vm.getTemplateScoreFileContent('/modules/users/client/templates/how-level-'+vm.lang+'.md')">
<div class="col-md-10 col-md-offset-1 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_LEVEL' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateScoreFileContent)"></span>
</div>
</div>
</div>
<div class="row margin-top-30" ng-init="vm.getMyPeers()">
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.INCOME_ESTIMATE' | translate}}</legend>
<ul>
<li ng-bind-html="vm.getMarkedCurrDownloadingString()"></li>
<li ng-bind-html="vm.getMarkedCurrSeedingString()"></li>
<li ng-bind-html="vm.getMarkedVipStatusString()"></li>
<li ng-bind-html="vm.getMarkedCurrUpSpeedString()"></li>
<li ng-bind-html="vm.getMarkedCurrDownSpeedString()"></li>
</ul>
<div class="alert alert-warning">
<span ng-bind-html="vm.getMarkedCurrScoreString()"></span>
<div class="row margin-top-30 margin-bottom-30"
ng-init="vm.getTemplateLevelFileContent('/modules/users/client/templates/how-score-'+vm.lang+'.md')">
<div class="col-md-10 col-md-offset-1 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_SCORE' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateLevelFileContent)"></span>
</div>
</div>
</div>
<div class="row margin-top-30"
ng-init="vm.getTemplateScoreFileContent('/modules/users/client/templates/how-level-'+vm.lang+'.md')">
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_LEVEL' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateScoreFileContent)"></span>
</div>
</div>
<div class="row margin-top-30 margin-bottom-30"
ng-init="vm.getTemplateLevelFileContent('/modules/users/client/templates/how-score-'+vm.lang+'.md')">
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_SCORE' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateLevelFileContent)"></span>
</div>
</div>
</div>
</section>

View File

@@ -1,3 +1,3 @@
<section class="container">
<section>
<div ui-view></div>
</section>

Some files were not shown because too many files have changed in this diff Show More