aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src
diff options
context:
space:
mode:
Diffstat (limited to 'client/src')
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html5
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts13
-rw-r--r--client/src/app/shared/buttons/action-dropdown.component.html16
-rw-r--r--client/src/app/shared/buttons/action-dropdown.component.scss21
-rw-r--r--client/src/app/shared/buttons/action-dropdown.component.ts20
-rw-r--r--client/src/app/shared/buttons/button.component.scss (renamed from client/src/app/shared/misc/button.component.scss)0
-rw-r--r--client/src/app/shared/buttons/delete-button.component.html6
-rw-r--r--client/src/app/shared/buttons/delete-button.component.ts (renamed from client/src/app/shared/misc/delete-button.component.ts)2
-rw-r--r--client/src/app/shared/buttons/edit-button.component.html (renamed from client/src/app/shared/misc/edit-button.component.html)4
-rw-r--r--client/src/app/shared/buttons/edit-button.component.ts (renamed from client/src/app/shared/misc/edit-button.component.ts)1
-rw-r--r--client/src/app/shared/misc/delete-button.component.html4
-rw-r--r--client/src/app/shared/shared.module.ts7
-rw-r--r--client/src/app/shared/users/user.model.ts35
13 files changed, 103 insertions, 31 deletions
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 166fafef0..ef5a6c648 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
@@ -30,8 +30,9 @@
30 <td>{{ user.roleLabel }}</td> 30 <td>{{ user.roleLabel }}</td>
31 <td>{{ user.createdAt }}</td> 31 <td>{{ user.createdAt }}</td>
32 <td class="action-cell"> 32 <td class="action-cell">
33 <my-edit-button [routerLink]="getRouterUserEditLink(user)"></my-edit-button> 33 <my-action-dropdown i18n-label label="Actions" [actions]="userActions" [entry]="user"></my-action-dropdown>
34 <my-delete-button (click)="removeUser(user)"></my-delete-button> 34 <!--<my-edit-button [routerLink]="getRouterUserEditLink(user)"></my-edit-button>-->
35 <!--<my-delete-button (click)="removeUser(user)"></my-delete-button>-->
35 </td> 36 </td>
36 </tr> 37 </tr>
37 </ng-template> 38 </ng-template>
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 ab25608c1..3c83859e0 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
@@ -5,6 +5,7 @@ import { ConfirmService } from '../../../core'
5import { RestPagination, RestTable, User } from '../../../shared' 5import { RestPagination, RestTable, User } from '../../../shared'
6import { UserService } from '../shared' 6import { UserService } from '../shared'
7import { I18n } from '@ngx-translate/i18n-polyfill' 7import { I18n } from '@ngx-translate/i18n-polyfill'
8import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
8 9
9@Component({ 10@Component({
10 selector: 'my-user-list', 11 selector: 'my-user-list',
@@ -17,6 +18,7 @@ export class UserListComponent extends RestTable implements OnInit {
17 rowsPerPage = 10 18 rowsPerPage = 10
18 sort: SortMeta = { field: 'createdAt', order: 1 } 19 sort: SortMeta = { field: 'createdAt', order: 1 }
19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 20 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
21 userActions: DropdownAction<User>[] = []
20 22
21 constructor ( 23 constructor (
22 private notificationsService: NotificationsService, 24 private notificationsService: NotificationsService,
@@ -25,6 +27,17 @@ export class UserListComponent extends RestTable implements OnInit {
25 private i18n: I18n 27 private i18n: I18n
26 ) { 28 ) {
27 super() 29 super()
30
31 this.userActions = [
32 {
33 type: 'edit',
34 linkBuilder: this.getRouterUserEditLink
35 },
36 {
37 type: 'delete',
38 handler: user => this.removeUser(user)
39 }
40 ]
28 } 41 }
29 42
30 ngOnInit () { 43 ngOnInit () {
diff --git a/client/src/app/shared/buttons/action-dropdown.component.html b/client/src/app/shared/buttons/action-dropdown.component.html
new file mode 100644
index 000000000..c87ba4c82
--- /dev/null
+++ b/client/src/app/shared/buttons/action-dropdown.component.html
@@ -0,0 +1,16 @@
1<div class="dropdown-root" dropdown container="body" dropup="true" placement="right" role="button">
2 <div class="action-button" dropdownToggle>
3 <span class="icon icon-action"></span>
4 </div>
5
6 <ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button">
7 <li role="menuitem" *ngFor="let action of actions">
8 <my-delete-button *ngIf="action.type === 'delete'" [label]="action.label" (click)="action.handler(entry)"></my-delete-button>
9 <my-edit-button *ngIf="action.type === 'edit'" [label]="action.label" [routerLink]="action.linkBuilder(entry)"></my-edit-button>
10
11 <a *ngIf="action.type === 'custom'" class="dropdown-item" href="#" (click)="action.handler(entry)">
12 <span *ngIf="action.iconClass" class="icon" [ngClass]="action.iconClass"></span> <ng-container>{{ action.label }}</ng-container>
13 </a>
14 </li>
15 </ul>
16</div> \ No newline at end of file
diff --git a/client/src/app/shared/buttons/action-dropdown.component.scss b/client/src/app/shared/buttons/action-dropdown.component.scss
new file mode 100644
index 000000000..cc459b972
--- /dev/null
+++ b/client/src/app/shared/buttons/action-dropdown.component.scss
@@ -0,0 +1,21 @@
1@import '_variables';
2@import '_mixins';
3
4.action-button {
5 @include peertube-button;
6 @include grey-button;
7
8 &:hover, &:active, &:focus {
9 background-color: $grey-color;
10 }
11
12 display: inline-block;
13 padding: 0 10px;
14
15 .icon-action {
16 @include icon(21px);
17
18 background-image: url('../../../assets/images/video/more.svg');
19 top: -1px;
20 }
21} \ No newline at end of file
diff --git a/client/src/app/shared/buttons/action-dropdown.component.ts b/client/src/app/shared/buttons/action-dropdown.component.ts
new file mode 100644
index 000000000..407d24b80
--- /dev/null
+++ b/client/src/app/shared/buttons/action-dropdown.component.ts
@@ -0,0 +1,20 @@
1import { Component, Input } from '@angular/core'
2
3export type DropdownAction<T> = {
4 type: 'custom' | 'delete' | 'edit'
5 label?: string
6 handler?: (T) => any
7 linkBuilder?: (T) => (string | number)[]
8 iconClass?: string
9}
10
11@Component({
12 selector: 'my-action-dropdown',
13 styleUrls: [ './action-dropdown.component.scss' ],
14 templateUrl: './action-dropdown.component.html'
15})
16
17export class ActionDropdownComponent<T> {
18 @Input() actions: DropdownAction<T>[] = []
19 @Input() entry: T
20}
diff --git a/client/src/app/shared/misc/button.component.scss b/client/src/app/shared/buttons/button.component.scss
index 343aea207..343aea207 100644
--- a/client/src/app/shared/misc/button.component.scss
+++ b/client/src/app/shared/buttons/button.component.scss
diff --git a/client/src/app/shared/buttons/delete-button.component.html b/client/src/app/shared/buttons/delete-button.component.html
new file mode 100644
index 000000000..792490219
--- /dev/null
+++ b/client/src/app/shared/buttons/delete-button.component.html
@@ -0,0 +1,6 @@
1<span class="action-button action-button-delete" [title]="label" role="button">
2 <span class="icon icon-delete-grey"></span>
3
4 <span class="button-label" *ngIf="label">{{ label }}</span>
5 <span class="button-label" i18n *ngIf="!label">Delete</span>
6</span>
diff --git a/client/src/app/shared/misc/delete-button.component.ts b/client/src/app/shared/buttons/delete-button.component.ts
index 2ffd98212..cd2bcccdf 100644
--- a/client/src/app/shared/misc/delete-button.component.ts
+++ b/client/src/app/shared/buttons/delete-button.component.ts
@@ -7,5 +7,5 @@ import { Component, Input } from '@angular/core'
7}) 7})
8 8
9export class DeleteButtonComponent { 9export class DeleteButtonComponent {
10 @Input() label = 'Delete' 10 @Input() label: string
11} 11}
diff --git a/client/src/app/shared/misc/edit-button.component.html b/client/src/app/shared/buttons/edit-button.component.html
index 78fbc326e..7efc54ce7 100644
--- a/client/src/app/shared/misc/edit-button.component.html
+++ b/client/src/app/shared/buttons/edit-button.component.html
@@ -1,4 +1,6 @@
1<a class="action-button action-button-edit" [routerLink]="routerLink" title="Edit"> 1<a class="action-button action-button-edit" [routerLink]="routerLink" title="Edit">
2 <span class="icon icon-edit"></span> 2 <span class="icon icon-edit"></span>
3 <span i18n class="button-label">Edit</span> 3
4 <span class="button-label" *ngIf="label">{{ label }}</span>
5 <span i18n class="button-label" *ngIf="!label">Edit</span>
4</a> 6</a>
diff --git a/client/src/app/shared/misc/edit-button.component.ts b/client/src/app/shared/buttons/edit-button.component.ts
index 201a618ec..7abaacc26 100644
--- a/client/src/app/shared/misc/edit-button.component.ts
+++ b/client/src/app/shared/buttons/edit-button.component.ts
@@ -7,5 +7,6 @@ import { Component, Input } from '@angular/core'
7}) 7})
8 8
9export class EditButtonComponent { 9export class EditButtonComponent {
10 @Input() label: string
10 @Input() routerLink = [] 11 @Input() routerLink = []
11} 12}
diff --git a/client/src/app/shared/misc/delete-button.component.html b/client/src/app/shared/misc/delete-button.component.html
deleted file mode 100644
index 7387d0a88..000000000
--- a/client/src/app/shared/misc/delete-button.component.html
+++ /dev/null
@@ -1,4 +0,0 @@
1<span class="action-button action-button-delete" [title]="label">
2 <span class="icon icon-delete-grey"></span>
3 <span class="button-label">{{ label }}</span>
4</span>
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index 62ce97102..94de3af9f 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -17,8 +17,8 @@ import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
17import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared' 17import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
18 18
19import { AUTH_INTERCEPTOR_PROVIDER } from './auth' 19import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
20import { DeleteButtonComponent } from './misc/delete-button.component' 20import { DeleteButtonComponent } from './buttons/delete-button.component'
21import { EditButtonComponent } from './misc/edit-button.component' 21import { EditButtonComponent } from './buttons/edit-button.component'
22import { FromNowPipe } from './misc/from-now.pipe' 22import { FromNowPipe } from './misc/from-now.pipe'
23import { LoaderComponent } from './misc/loader.component' 23import { LoaderComponent } from './misc/loader.component'
24import { NumberFormatterPipe } from './misc/number-formatter.pipe' 24import { NumberFormatterPipe } from './misc/number-formatter.pipe'
@@ -52,6 +52,7 @@ import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validator
52import { VideoCaptionService } from '@app/shared/video-caption' 52import { VideoCaptionService } from '@app/shared/video-caption'
53import { PeertubeCheckboxComponent } from '@app/shared/forms/peertube-checkbox.component' 53import { PeertubeCheckboxComponent } from '@app/shared/forms/peertube-checkbox.component'
54import { VideoImportService } from '@app/shared/video-import/video-import.service' 54import { VideoImportService } from '@app/shared/video-import/video-import.service'
55import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component'
55 56
56@NgModule({ 57@NgModule({
57 imports: [ 58 imports: [
@@ -78,6 +79,7 @@ import { VideoImportService } from '@app/shared/video-import/video-import.servic
78 VideoFeedComponent, 79 VideoFeedComponent,
79 DeleteButtonComponent, 80 DeleteButtonComponent,
80 EditButtonComponent, 81 EditButtonComponent,
82 ActionDropdownComponent,
81 NumberFormatterPipe, 83 NumberFormatterPipe,
82 ObjectLengthPipe, 84 ObjectLengthPipe,
83 FromNowPipe, 85 FromNowPipe,
@@ -110,6 +112,7 @@ import { VideoImportService } from '@app/shared/video-import/video-import.servic
110 VideoFeedComponent, 112 VideoFeedComponent,
111 DeleteButtonComponent, 113 DeleteButtonComponent,
112 EditButtonComponent, 114 EditButtonComponent,
115 ActionDropdownComponent,
113 MarkdownTextareaComponent, 116 MarkdownTextareaComponent,
114 InfiniteScrollerDirective, 117 InfiniteScrollerDirective,
115 HelpComponent, 118 HelpComponent,
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts
index 581ea7859..2748001d0 100644
--- a/client/src/app/shared/users/user.model.ts
+++ b/client/src/app/shared/users/user.model.ts
@@ -7,7 +7,6 @@ import {
7 VideoChannel 7 VideoChannel
8} from '../../../../../shared' 8} from '../../../../../shared'
9import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type' 9import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type'
10import { Actor } from '@app/shared/actor/actor.model'
11import { Account } from '@app/shared/account/account.model' 10import { Account } from '@app/shared/account/account.model'
12import { Avatar } from '../../../../../shared/models/avatars/avatar.model' 11import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
13 12
@@ -22,6 +21,9 @@ export type UserConstructorHash = {
22 createdAt?: Date, 21 createdAt?: Date,
23 account?: AccountServerModel, 22 account?: AccountServerModel,
24 videoChannels?: VideoChannel[] 23 videoChannels?: VideoChannel[]
24
25 blocked?: boolean
26 blockedReason?: string
25} 27}
26export class User implements UserServerModel { 28export class User implements UserServerModel {
27 id: number 29 id: number
@@ -35,35 +37,26 @@ export class User implements UserServerModel {
35 videoChannels: VideoChannel[] 37 videoChannels: VideoChannel[]
36 createdAt: Date 38 createdAt: Date
37 39
40 blocked: boolean
41 blockedReason?: string
42
38 constructor (hash: UserConstructorHash) { 43 constructor (hash: UserConstructorHash) {
39 this.id = hash.id 44 this.id = hash.id
40 this.username = hash.username 45 this.username = hash.username
41 this.email = hash.email 46 this.email = hash.email
42 this.role = hash.role 47 this.role = hash.role
43 48
49 this.videoChannels = hash.videoChannels
50 this.videoQuota = hash.videoQuota
51 this.nsfwPolicy = hash.nsfwPolicy
52 this.autoPlayVideo = hash.autoPlayVideo
53 this.createdAt = hash.createdAt
54 this.blocked = hash.blocked
55 this.blockedReason = hash.blockedReason
56
44 if (hash.account !== undefined) { 57 if (hash.account !== undefined) {
45 this.account = new Account(hash.account) 58 this.account = new Account(hash.account)
46 } 59 }
47
48 if (hash.videoChannels !== undefined) {
49 this.videoChannels = hash.videoChannels
50 }
51
52 if (hash.videoQuota !== undefined) {
53 this.videoQuota = hash.videoQuota
54 }
55
56 if (hash.nsfwPolicy !== undefined) {
57 this.nsfwPolicy = hash.nsfwPolicy
58 }
59
60 if (hash.autoPlayVideo !== undefined) {
61 this.autoPlayVideo = hash.autoPlayVideo
62 }
63
64 if (hash.createdAt !== undefined) {
65 this.createdAt = hash.createdAt
66 }
67 } 60 }
68 61
69 get accountAvatarUrl () { 62 get accountAvatarUrl () {