From 791645e620fb98c6e7c32271d91d91ff7e41b892 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 8 Oct 2018 15:15:11 +0200 Subject: Add bulk actions in users table --- .../users/user-list/user-list.component.html | 31 +++++++- .../users/user-list/user-list.component.scss | 11 +++ .../+admin/users/user-list/user-list.component.ts | 93 +++++++++++++++++++++- client/src/app/header/header.component.html | 4 +- .../shared/buttons/action-dropdown.component.html | 8 +- .../shared/buttons/action-dropdown.component.scss | 14 +++- .../shared/buttons/action-dropdown.component.ts | 4 +- .../moderation/user-ban-modal.component.html | 2 +- .../shared/moderation/user-ban-modal.component.ts | 23 +++--- .../user-moderation-dropdown.component.html | 2 +- .../user-moderation-dropdown.component.ts | 9 +-- client/src/app/shared/users/user.service.ts | 39 ++++++--- client/src/sass/primeng-custom.scss | 38 ++++++++- 13 files changed, 233 insertions(+), 45 deletions(-) (limited to 'client/src') diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html index cca057ba1..9d1f2e34a 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.html +++ b/client/src/app/+admin/users/user-list/user-list.component.html @@ -10,10 +10,31 @@ + +
+
+ + +
+ +
+ +
+
+
+ + + Username Email Video quota @@ -25,12 +46,17 @@ - + + + + + + {{ user.username }} (banned) @@ -40,7 +66,7 @@ {{ user.roleLabel }} {{ user.createdAt }} - + @@ -56,3 +82,4 @@
+ diff --git a/client/src/app/+admin/users/user-list/user-list.component.scss b/client/src/app/+admin/users/user-list/user-list.component.scss index 47291918d..01f43dfe1 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.scss +++ b/client/src/app/+admin/users/user-list/user-list.component.scss @@ -15,4 +15,15 @@ tr.banned { .ban-reason-label { font-weight: $font-semibold; +} + +.caption { + height: 40px; + display: flex; + justify-content: space-between; + align-items: center; + + input { + @include peertube-input-text(250px); + } } \ No newline at end of file diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts index dee3ed643..f3e7e0ead 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/users/user-list/user-list.component.ts @@ -1,10 +1,12 @@ -import { Component, OnInit } from '@angular/core' +import { Component, OnInit, ViewChild } from '@angular/core' import { NotificationsService } from 'angular2-notifications' import { SortMeta } from 'primeng/components/common/sortmeta' import { ConfirmService } from '../../../core' import { RestPagination, RestTable, UserService } from '../../../shared' import { I18n } from '@ngx-translate/i18n-polyfill' import { User } from '../../../../../../shared' +import { UserBanModalComponent } from '@app/shared/moderation' +import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' @Component({ selector: 'my-user-list', @@ -12,12 +14,17 @@ import { User } from '../../../../../../shared' styleUrls: [ './user-list.component.scss' ] }) export class UserListComponent extends RestTable implements OnInit { + @ViewChild('userBanModal') userBanModal: UserBanModalComponent + users: User[] = [] totalRecords = 0 rowsPerPage = 10 sort: SortMeta = { field: 'createdAt', order: 1 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + selectedUsers: User[] = [] + bulkUserActions: DropdownAction[] = [] + constructor ( private notificationsService: NotificationsService, private confirmService: ConfirmService, @@ -29,13 +36,28 @@ export class UserListComponent extends RestTable implements OnInit { ngOnInit () { this.loadSort() - } - onUserChanged () { - this.loadData() + this.bulkUserActions = [ + { + label: this.i18n('Delete'), + handler: users => this.removeUsers(users) + }, + { + label: this.i18n('Ban'), + handler: users => this.openBanUserModal(users), + isDisplayed: users => users.every(u => u.blocked === false) + }, + { + label: this.i18n('Unban'), + handler: users => this.unbanUsers(users), + isDisplayed: users => users.every(u => u.blocked === true) + } + ] } protected loadData () { + this.selectedUsers = [] + this.userService.getUsers(this.pagination, this.sort) .subscribe( resultList => { @@ -46,4 +68,67 @@ export class UserListComponent extends RestTable implements OnInit { err => this.notificationsService.error(this.i18n('Error'), err.message) ) } + + openBanUserModal (users: User[]) { + for (const user of users) { + if (user.username === 'root') { + this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot ban root.')) + return + } + } + + this.userBanModal.openModal(users) + } + + onUsersBanned () { + this.loadData() + } + + async unbanUsers (users: User[]) { + const message = this.i18n('Do you really want to unban {{num}} users?', { num: users.length }) + + const res = await this.confirmService.confirm(message, this.i18n('Unban')) + if (res === false) return + + this.userService.unbanUsers(users) + .subscribe( + () => { + const message = this.i18n('{{num}} users unbanned.', { num: users.length }) + + this.notificationsService.success(this.i18n('Success'), message) + this.loadData() + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } + + async removeUsers (users: User[]) { + for (const user of users) { + if (user.username === 'root') { + this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot delete root.')) + return + } + } + + const message = this.i18n('If you remove these users, you will not be able to create others with the same username!') + const res = await this.confirmService.confirm(message, this.i18n('Delete')) + if (res === false) return + + this.userService.removeUser(users).subscribe( + () => { + this.notificationsService.success( + this.i18n('Success'), + this.i18n('{{num}} users deleted.', { num: users.length }) + ) + this.loadData() + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } + + isInSelectionMode () { + return this.selectedUsers.length !== 0 + } } diff --git a/client/src/app/header/header.component.html b/client/src/app/header/header.component.html index a04354db5..c23e0c55d 100644 --- a/client/src/app/header/header.component.html +++ b/client/src/app/header/header.component.html @@ -1,6 +1,6 @@ diff --git a/client/src/app/shared/buttons/action-dropdown.component.html b/client/src/app/shared/buttons/action-dropdown.component.html index 8110e2515..111627424 100644 --- a/client/src/app/shared/buttons/action-dropdown.component.html +++ b/client/src/app/shared/buttons/action-dropdown.component.html @@ -1,6 +1,10 @@