Add ability to ban/unban users
This commit is contained in:
parent
63347a0ff9
commit
141b177db0
|
@ -13,6 +13,7 @@ import { JobService } from './jobs/shared/job.service'
|
||||||
import { UserCreateComponent, UserListComponent, UsersComponent, UserService, UserUpdateComponent } from './users'
|
import { UserCreateComponent, UserListComponent, UsersComponent, UserService, UserUpdateComponent } from './users'
|
||||||
import { VideoAbuseListComponent, VideoAbusesComponent } from './video-abuses'
|
import { VideoAbuseListComponent, VideoAbusesComponent } from './video-abuses'
|
||||||
import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-blacklist'
|
import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-blacklist'
|
||||||
|
import { UserBanModalComponent } from '@app/+admin/users/user-list/user-ban-modal.component'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -33,6 +34,7 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl
|
||||||
UserCreateComponent,
|
UserCreateComponent,
|
||||||
UserUpdateComponent,
|
UserUpdateComponent,
|
||||||
UserListComponent,
|
UserListComponent,
|
||||||
|
UserBanModalComponent,
|
||||||
|
|
||||||
VideoBlacklistComponent,
|
VideoBlacklistComponent,
|
||||||
VideoBlacklistListComponent,
|
VideoBlacklistListComponent,
|
||||||
|
|
|
@ -59,6 +59,18 @@ export class UserService {
|
||||||
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
banUser (user: User, reason?: string) {
|
||||||
|
const body = reason ? { reason } : {}
|
||||||
|
|
||||||
|
return this.authHttp.post(UserService.BASE_USERS_URL + user.id + '/block', body)
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
unbanUser (user: User) {
|
||||||
|
return this.authHttp.post(UserService.BASE_USERS_URL + user.id + '/unblock', {})
|
||||||
|
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||||
|
}
|
||||||
|
|
||||||
private formatUser (user: User) {
|
private formatUser (user: User) {
|
||||||
let videoQuota
|
let videoQuota
|
||||||
if (user.videoQuota === -1) {
|
if (user.videoQuota === -1) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<ng-template #modal>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 i18n class="modal-title">Ban {{ userToBan.username }}</h4>
|
||||||
|
<span class="close" aria-hidden="true" (click)="hideBanUserModal()"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<form novalidate [formGroup]="form" (ngSubmit)="banUser()">
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea i18n-placeholder placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
|
||||||
|
</textarea>
|
||||||
|
<div *ngIf="formErrors.reason" class="form-error">
|
||||||
|
{{ formErrors.reason }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div i18n>
|
||||||
|
A banned user will no longer be able to login.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group inputs">
|
||||||
|
<span i18n class="action-button action-button-cancel" (click)="hideBanUserModal()">Cancel</span>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="submit" i18n-value value="Ban this user" class="action-button-submit"
|
||||||
|
[disabled]="!form.valid"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ng-template>
|
|
@ -0,0 +1,6 @@
|
||||||
|
@import 'variables';
|
||||||
|
@import 'mixins';
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
@include peertube-textarea(100%, 60px);
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
|
||||||
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
|
import { FormReactive, User, UserValidatorsService } from '../../../shared'
|
||||||
|
import { UserService } from '../shared'
|
||||||
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||||
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-user-ban-modal',
|
||||||
|
templateUrl: './user-ban-modal.component.html',
|
||||||
|
styleUrls: [ './user-ban-modal.component.scss' ]
|
||||||
|
})
|
||||||
|
export class UserBanModalComponent extends FormReactive implements OnInit {
|
||||||
|
@ViewChild('modal') modal: NgbModal
|
||||||
|
@Output() userBanned = new EventEmitter<User>()
|
||||||
|
|
||||||
|
private userToBan: User
|
||||||
|
private openedModal: NgbModalRef
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
protected formValidatorService: FormValidatorService,
|
||||||
|
private modalService: NgbModal,
|
||||||
|
private notificationsService: NotificationsService,
|
||||||
|
private userService: UserService,
|
||||||
|
private userValidatorsService: UserValidatorsService,
|
||||||
|
private i18n: I18n
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.buildForm({
|
||||||
|
reason: this.userValidatorsService.USER_BAN_REASON
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
openModal (user: User) {
|
||||||
|
this.userToBan = user
|
||||||
|
this.openedModal = this.modalService.open(this.modal)
|
||||||
|
}
|
||||||
|
|
||||||
|
hideBanUserModal () {
|
||||||
|
this.userToBan = undefined
|
||||||
|
this.openedModal.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
async banUser () {
|
||||||
|
const reason = this.form.value['reason'] || undefined
|
||||||
|
|
||||||
|
this.userService.banUser(this.userToBan, reason)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('User {{username}} banned.', { username: this.userToBan.username })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.userBanned.emit(this.userToBan)
|
||||||
|
this.hideBanUserModal()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,31 +9,50 @@
|
||||||
|
|
||||||
<p-table
|
<p-table
|
||||||
[value]="users" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
|
[value]="users" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
|
||||||
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
|
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
|
||||||
>
|
>
|
||||||
<ng-template pTemplate="header">
|
<ng-template pTemplate="header">
|
||||||
<tr>
|
<tr>
|
||||||
|
<th style="width: 40px"></th>
|
||||||
<th i18n pSortableColumn="username">Username <p-sortIcon field="username"></p-sortIcon></th>
|
<th i18n pSortableColumn="username">Username <p-sortIcon field="username"></p-sortIcon></th>
|
||||||
<th i18n>Email</th>
|
<th i18n>Email</th>
|
||||||
<th i18n>Video quota</th>
|
<th i18n>Video quota</th>
|
||||||
<th i18n>Role</th>
|
<th i18n>Role</th>
|
||||||
<th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
|
<th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
|
||||||
<th></th>
|
<th style="width: 50px;"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template pTemplate="body" let-user>
|
<ng-template pTemplate="body" let-expanded="expanded" let-user>
|
||||||
<tr>
|
|
||||||
<td>{{ user.username }}</td>
|
<tr [ngClass]="{ banned: user.blocked }">
|
||||||
|
<td>
|
||||||
|
<span *ngIf="user.blockedReason" class="expander" [pRowToggler]="user">
|
||||||
|
<i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ user.username }}
|
||||||
|
<span *ngIf="user.blocked" class="banned-info">(banned)</span>
|
||||||
|
</td>
|
||||||
<td>{{ user.email }}</td>
|
<td>{{ user.email }}</td>
|
||||||
<td>{{ user.videoQuota }}</td>
|
<td>{{ user.videoQuota }}</td>
|
||||||
<td>{{ user.roleLabel }}</td>
|
<td>{{ user.roleLabel }}</td>
|
||||||
<td>{{ user.createdAt }}</td>
|
<td>{{ user.createdAt }}</td>
|
||||||
<td class="action-cell">
|
<td class="action-cell">
|
||||||
<my-action-dropdown i18n-label label="Actions" [actions]="userActions" [entry]="user"></my-action-dropdown>
|
<my-action-dropdown i18n-label label="Actions" [actions]="userActions" [entry]="user"></my-action-dropdown>
|
||||||
<!--<my-edit-button [routerLink]="getRouterUserEditLink(user)"></my-edit-button>-->
|
</td>
|
||||||
<!--<my-delete-button (click)="removeUser(user)"></my-delete-button>-->
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template pTemplate="rowexpansion" let-user>
|
||||||
|
<tr class="user-blocked-reason">
|
||||||
|
<td colspan="7">
|
||||||
|
<span i18n class="ban-reason-label">Ban reason:</span>
|
||||||
|
{{ user.blockedReason }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-table>
|
</p-table>
|
||||||
|
|
||||||
|
<my-user-ban-modal #userBanModal (userBanned)="onUserBanned()"></my-user-ban-modal>
|
|
@ -4,3 +4,21 @@
|
||||||
.add-button {
|
.add-button {
|
||||||
@include create-button('../../../../assets/images/global/add.svg');
|
@include create-button('../../../../assets/images/global/add.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my-action-dropdown /deep/ .icon {
|
||||||
|
&.icon-ban {
|
||||||
|
background-image: url('../../../../assets/images/global/edit-black.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.banned {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banned-info {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ban-reason-label {
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, ViewChild } from '@angular/core'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { SortMeta } from 'primeng/components/common/sortmeta'
|
import { SortMeta } from 'primeng/components/common/sortmeta'
|
||||||
import { ConfirmService } from '../../../core'
|
import { ConfirmService } from '../../../core'
|
||||||
|
@ -6,6 +6,8 @@ import { RestPagination, RestTable, User } from '../../../shared'
|
||||||
import { UserService } from '../shared'
|
import { UserService } from '../shared'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||||
|
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||||
|
import { UserBanModalComponent } from '@app/+admin/users/user-list/user-ban-modal.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-user-list',
|
selector: 'my-user-list',
|
||||||
|
@ -13,6 +15,8 @@ import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||||
styleUrls: [ './user-list.component.scss' ]
|
styleUrls: [ './user-list.component.scss' ]
|
||||||
})
|
})
|
||||||
export class UserListComponent extends RestTable implements OnInit {
|
export class UserListComponent extends RestTable implements OnInit {
|
||||||
|
@ViewChild('userBanModal') userBanModal: UserBanModalComponent
|
||||||
|
|
||||||
users: User[] = []
|
users: User[] = []
|
||||||
totalRecords = 0
|
totalRecords = 0
|
||||||
rowsPerPage = 10
|
rowsPerPage = 10
|
||||||
|
@ -20,6 +24,9 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
||||||
userActions: DropdownAction<User>[] = []
|
userActions: DropdownAction<User>[] = []
|
||||||
|
|
||||||
|
private userToBan: User
|
||||||
|
private openedModal: NgbModalRef
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private confirmService: ConfirmService,
|
private confirmService: ConfirmService,
|
||||||
|
@ -30,12 +37,22 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
|
|
||||||
this.userActions = [
|
this.userActions = [
|
||||||
{
|
{
|
||||||
type: 'edit',
|
label: this.i18n('Edit'),
|
||||||
linkBuilder: this.getRouterUserEditLink
|
linkBuilder: this.getRouterUserEditLink
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'delete',
|
label: this.i18n('Delete'),
|
||||||
handler: user => this.removeUser(user)
|
handler: user => this.removeUser(user)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.i18n('Ban'),
|
||||||
|
handler: user => this.openBanUserModal(user),
|
||||||
|
isDisplayed: user => !user.blocked
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.i18n('Unban'),
|
||||||
|
handler: user => this.unbanUser(user),
|
||||||
|
isDisplayed: user => user.blocked
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -44,6 +61,43 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
this.loadSort()
|
this.loadSort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hideBanUserModal () {
|
||||||
|
this.userToBan = undefined
|
||||||
|
this.openedModal.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
openBanUserModal (user: User) {
|
||||||
|
if (user.username === 'root') {
|
||||||
|
this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot ban root.'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userBanModal.openModal(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
onUserBanned () {
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
async unbanUser (user: User) {
|
||||||
|
const message = this.i18n('Do you really want to unban {{username}}?', { username: user.username })
|
||||||
|
const res = await this.confirmService.confirm(message, this.i18n('Unban'))
|
||||||
|
if (res === false) return
|
||||||
|
|
||||||
|
this.userService.unbanUser(user)
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
this.notificationsService.success(
|
||||||
|
this.i18n('Success'),
|
||||||
|
this.i18n('User {{username}} unbanned.', { username: user.username })
|
||||||
|
)
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error(this.i18n('Error'), err.message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async removeUser (user: User) {
|
async removeUser (user: User) {
|
||||||
if (user.username === 'root') {
|
if (user.username === 'root') {
|
||||||
this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot delete root.'))
|
this.notificationsService.error(this.i18n('Error'), this.i18n('You cannot delete root.'))
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--<ng-template #forgotPasswordModal (onShown)="onForgotPasswordModalShown()">-->
|
|
||||||
<ng-template #forgotPasswordModal>
|
<ng-template #forgotPasswordModal>
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 i18n class="modal-title">Forgot your password</h4>
|
<h4 i18n class="modal-title">Forgot your password</h4>
|
||||||
|
|
|
@ -69,7 +69,7 @@ export class LoginComponent extends FormReactive implements OnInit {
|
||||||
askResetPassword () {
|
askResetPassword () {
|
||||||
this.userService.askResetPassword(this.forgotPasswordEmail)
|
this.userService.askResetPassword(this.forgotPasswordEmail)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
() => {
|
||||||
const message = this.i18n(
|
const message = this.i18n(
|
||||||
'An email with the reset password instructions will be sent to {{email}}.',
|
'An email with the reset password instructions will be sent to {{email}}.',
|
||||||
{ email: this.forgotPasswordEmail }
|
{ email: this.forgotPasswordEmail }
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<div class="dropdown-root" dropdown container="body" dropup="true" placement="right" role="button">
|
<div class="dropdown-root" ngbDropdown [placement]="placement">
|
||||||
<div class="action-button" dropdownToggle>
|
<div class="action-button" ngbDropdownToggle role="button">
|
||||||
<span class="icon icon-action"></span>
|
<span class="icon icon-action"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button">
|
<div ngbDropdownMenu class="dropdown-menu">
|
||||||
<li role="menuitem" *ngFor="let action of actions">
|
<ng-container *ngFor="let action of actions">
|
||||||
<my-delete-button *ngIf="action.type === 'delete'" [label]="action.label" (click)="action.handler(entry)"></my-delete-button>
|
<div class="dropdown-item" *ngIf="action.isDisplayed === undefined || action.isDisplayed(entry) === true">
|
||||||
<my-edit-button *ngIf="action.type === 'edit'" [label]="action.label" [routerLink]="action.linkBuilder(entry)"></my-edit-button>
|
<a *ngIf="action.linkBuilder" class="dropdown-item" [routerLink]="action.linkBuilder(entry)">{{ action.label }}</a>
|
||||||
|
|
||||||
<a *ngIf="action.type === 'custom'" class="dropdown-item" href="#" (click)="action.handler(entry)">
|
<span *ngIf="!action.linkBuilder" class="custom-action" class="dropdown-item" (click)="action.handler(entry)" role="button">
|
||||||
<span *ngIf="action.iconClass" class="icon" [ngClass]="action.iconClass"></span> <ng-container>{{ action.label }}</ng-container>
|
{{ action.label }}
|
||||||
</a>
|
</span>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
</ng-container>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -5,13 +5,17 @@
|
||||||
@include peertube-button;
|
@include peertube-button;
|
||||||
@include grey-button;
|
@include grey-button;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 10px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover, &:active, &:focus {
|
&:hover, &:active, &:focus {
|
||||||
background-color: $grey-color;
|
background-color: $grey-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 10px;
|
|
||||||
|
|
||||||
.icon-action {
|
.icon-action {
|
||||||
@include icon(21px);
|
@include icon(21px);
|
||||||
|
|
||||||
|
@ -19,3 +23,10 @@
|
||||||
top: -1px;
|
top: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
.dropdown-item {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
export type DropdownAction<T> = {
|
export type DropdownAction<T> = {
|
||||||
type: 'custom' | 'delete' | 'edit'
|
|
||||||
label?: string
|
label?: string
|
||||||
handler?: (T) => any
|
handler?: (T) => any
|
||||||
linkBuilder?: (T) => (string | number)[]
|
linkBuilder?: (T) => (string | number)[]
|
||||||
iconClass?: string
|
isDisplayed?: (T) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -17,4 +16,5 @@ export type DropdownAction<T> = {
|
||||||
export class ActionDropdownComponent<T> {
|
export class ActionDropdownComponent<T> {
|
||||||
@Input() actions: DropdownAction<T>[] = []
|
@Input() actions: DropdownAction<T>[] = []
|
||||||
@Input() entry: T
|
@Input() entry: T
|
||||||
|
@Input() placement = 'left'
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ export class UserValidatorsService {
|
||||||
readonly USER_DESCRIPTION: BuildFormValidator
|
readonly USER_DESCRIPTION: BuildFormValidator
|
||||||
readonly USER_TERMS: BuildFormValidator
|
readonly USER_TERMS: BuildFormValidator
|
||||||
|
|
||||||
|
readonly USER_BAN_REASON: BuildFormValidator
|
||||||
|
|
||||||
constructor (private i18n: I18n) {
|
constructor (private i18n: I18n) {
|
||||||
|
|
||||||
this.USER_USERNAME = {
|
this.USER_USERNAME = {
|
||||||
|
@ -99,5 +101,16 @@ export class UserValidatorsService {
|
||||||
'required': this.i18n('You must to agree with the instance terms in order to registering on it.')
|
'required': this.i18n('You must to agree with the instance terms in order to registering on it.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.USER_BAN_REASON = {
|
||||||
|
VALIDATORS: [
|
||||||
|
Validators.minLength(3),
|
||||||
|
Validators.maxLength(250)
|
||||||
|
],
|
||||||
|
MESSAGES: {
|
||||||
|
'minlength': this.i18n('Ban reason must be at least 3 characters long.'),
|
||||||
|
'maxlength': this.i18n('Ban reason cannot be more than 250 characters long.')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,8 +310,4 @@ table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bs-dropdown-container {
|
|
||||||
z-index: 10000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,13 @@ p-table {
|
||||||
td {
|
td {
|
||||||
border: 1px solid #E5E5E5 !important;
|
border: 1px solid #E5E5E5 !important;
|
||||||
padding-left: 15px !important;
|
padding-left: 15px !important;
|
||||||
|
|
||||||
|
&:not(.action-cell) {
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
text-overflow: ellipsis !important;
|
text-overflow: ellipsis !important;
|
||||||
white-space: nowrap !important;
|
white-space: nowrap !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tr {
|
tr {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
|
|
Loading…
Reference in New Issue