aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-06-15 13:18:22 +0200
committerGitHub <noreply@github.com>2020-06-15 13:18:22 +0200
commit228393302d98136d4dc35c5f197edc8cebd5d64f (patch)
treef92b3ad80bcc9c89088ff1d4de5ebff76a3f46ed
parent7dfe35288613967f5ac69cd46901ec60c5050b93 (diff)
downloadPeerTube-228393302d98136d4dc35c5f197edc8cebd5d64f.tar.gz
PeerTube-228393302d98136d4dc35c5f197edc8cebd5d64f.tar.zst
PeerTube-228393302d98136d4dc35c5f197edc8cebd5d64f.zip
factorize account/server blocklists for users and instance (#2875)
-rw-r--r--client/src/app/+admin/admin.module.ts5
-rw-r--r--client/src/app/+admin/follows/followers-list/followers-list.component.html2
-rw-r--r--client/src/app/+admin/follows/following-list/following-list.component.html2
-rw-r--r--client/src/app/+admin/follows/follows.component.scss4
-rw-r--r--client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html2
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html2
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts67
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts81
-rw-r--r--client/src/app/+admin/moderation/moderation.component.scss4
-rw-r--r--client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html2
-rw-r--r--client/src/app/+admin/moderation/video-block-list/video-block-list.component.html2
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.html27
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.scss7
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts56
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.html27
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.scss7
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts57
-rw-r--r--client/src/app/+my-account/my-account-routing.module.ts2
-rw-r--r--client/src/app/+my-account/my-account.component.ts2
-rw-r--r--client/src/app/shared/blocklist/account-blocklist.component.html64
-rw-r--r--client/src/app/shared/blocklist/account-blocklist.component.scss16
-rw-r--r--client/src/app/shared/blocklist/account-blocklist.component.ts79
-rw-r--r--client/src/app/shared/blocklist/blocklist.service.ts18
-rw-r--r--client/src/app/shared/blocklist/index.ts2
-rw-r--r--client/src/app/shared/blocklist/server-blocklist.component.html (renamed from client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html)2
-rw-r--r--client/src/app/shared/blocklist/server-blocklist.component.scss (renamed from client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss)9
-rw-r--r--client/src/app/shared/blocklist/server-blocklist.component.ts101
-rw-r--r--client/src/app/shared/shared.module.ts7
-rw-r--r--client/src/sass/application.scss2
-rw-r--r--client/src/sass/include/_mixins.scss9
30 files changed, 326 insertions, 341 deletions
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index eb073f709..eccec8a49 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -27,7 +27,6 @@ import { SelectButtonModule } from 'primeng/selectbutton'
27import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' 27import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
28import { VideoRedundancyInformationComponent } from '@app/+admin/follows/video-redundancies-list/video-redundancy-information.component' 28import { VideoRedundancyInformationComponent } from '@app/+admin/follows/video-redundancies-list/video-redundancy-information.component'
29import { ChartModule } from 'primeng/chart' 29import { ChartModule } from 'primeng/chart'
30import { BatchDomainsModalComponent } from './config/shared/batch-domains-modal.component'
31import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video-abuse-details.component' 30import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video-abuse-details.component'
32 31
33@NgModule({ 32@NgModule({
@@ -76,9 +75,7 @@ import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video-
76 DebugComponent, 75 DebugComponent,
77 76
78 ConfigComponent, 77 ConfigComponent,
79 EditCustomConfigComponent, 78 EditCustomConfigComponent
80
81 BatchDomainsModalComponent
82 ], 79 ],
83 80
84 exports: [ 81 exports: [
diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.html b/client/src/app/+admin/follows/followers-list/followers-list.component.html
index 298871fce..48b5681f4 100644
--- a/client/src/app/+admin/follows/followers-list/followers-list.component.html
+++ b/client/src/app/+admin/follows/followers-list/followers-list.component.html
@@ -56,7 +56,7 @@
56 <ng-template pTemplate="emptymessage"> 56 <ng-template pTemplate="emptymessage">
57 <tr> 57 <tr>
58 <td colspan="6"> 58 <td colspan="6">
59 <div class="empty-table-message"> 59 <div class="no-results">
60 <ng-container *ngIf="search" i18n>No follower found matching current filters.</ng-container> 60 <ng-container *ngIf="search" i18n>No follower found matching current filters.</ng-container>
61 <ng-container *ngIf="!search" i18n>Your instance doesn't have any follower.</ng-container> 61 <ng-container *ngIf="!search" i18n>Your instance doesn't have any follower.</ng-container>
62 </div> 62 </div>
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.html b/client/src/app/+admin/follows/following-list/following-list.component.html
index ed521d650..a8fbf65d4 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.html
+++ b/client/src/app/+admin/follows/following-list/following-list.component.html
@@ -58,7 +58,7 @@
58 <ng-template pTemplate="emptymessage"> 58 <ng-template pTemplate="emptymessage">
59 <tr> 59 <tr>
60 <td colspan="6"> 60 <td colspan="6">
61 <div class="empty-table-message"> 61 <div class="no-results">
62 <ng-container *ngIf="search" i18n>No host found matching current filters.</ng-container> 62 <ng-container *ngIf="search" i18n>No host found matching current filters.</ng-container>
63 <ng-container *ngIf="!search" i18n>Your instance is not following anyone.</ng-container> 63 <ng-container *ngIf="!search" i18n>Your instance is not following anyone.</ng-container>
64 </div> 64 </div>
diff --git a/client/src/app/+admin/follows/follows.component.scss b/client/src/app/+admin/follows/follows.component.scss
index 32394f698..0cffcb555 100644
--- a/client/src/app/+admin/follows/follows.component.scss
+++ b/client/src/app/+admin/follows/follows.component.scss
@@ -4,7 +4,3 @@
4 flex-grow: 0; 4 flex-grow: 0;
5 margin-right: 30px; 5 margin-right: 30px;
6} 6}
7
8.empty-table-message {
9 @include empty-state;
10}
diff --git a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
index c08154bcd..44586cb67 100644
--- a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
+++ b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
@@ -73,7 +73,7 @@
73 <ng-template pTemplate="emptymessage"> 73 <ng-template pTemplate="emptymessage">
74 <tr> 74 <tr>
75 <td colspan="6"> 75 <td colspan="6">
76 <div class="empty-table-message"> 76 <div class="no-results">
77 <ng-container *ngIf="isDisplayingRemoteVideos()" i18n>Your instance doesn't mirror any video.</ng-container> 77 <ng-container *ngIf="isDisplayingRemoteVideos()" i18n>Your instance doesn't mirror any video.</ng-container>
78 <ng-container *ngIf="!isDisplayingRemoteVideos()" i18n>Your instance has no mirrored videos.</ng-container> 78 <ng-container *ngIf="!isDisplayingRemoteVideos()" i18n>Your instance has no mirrored videos.</ng-container>
79 </div> 79 </div>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
index b7d40be60..486785f35 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
@@ -54,7 +54,7 @@
54 <ng-template pTemplate="emptymessage"> 54 <ng-template pTemplate="emptymessage">
55 <tr> 55 <tr>
56 <td colspan="6"> 56 <td colspan="6">
57 <div class="empty-table-message"> 57 <div class="no-results">
58 <ng-container *ngIf="search" i18n>No account found matching current filters.</ng-container> 58 <ng-container *ngIf="search" i18n>No account found matching current filters.</ng-container>
59 <ng-container *ngIf="!search" i18n>No account found.</ng-container> 59 <ng-container *ngIf="!search" i18n>No account found.</ng-container>
60 </div> 60 </div>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
index 73a9ae75d..90a176194 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.ts
@@ -1,70 +1,15 @@
1import { Component, OnInit } from '@angular/core' 1import { Component } from '@angular/core'
2import { Notifier } from '@app/core' 2import { GenericAccountBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/api'
6import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
7import { Actor } from '@app/shared/actor/actor.model'
8 3
9@Component({ 4@Component({
10 selector: 'my-instance-account-blocklist', 5 selector: 'my-instance-account-blocklist',
11 styleUrls: [ '../moderation.component.scss', './instance-account-blocklist.component.scss' ], 6 styleUrls: [ '../moderation.component.scss', '../../../shared/blocklist/account-blocklist.component.scss' ],
12 templateUrl: './instance-account-blocklist.component.html' 7 templateUrl: '../../../shared/blocklist/account-blocklist.component.html'
13}) 8})
14export class InstanceAccountBlocklistComponent extends RestTable implements OnInit { 9export class InstanceAccountBlocklistComponent extends GenericAccountBlocklistComponent {
15 blockedAccounts: AccountBlock[] = [] 10 mode = BlocklistComponentType.Instance
16 totalRecords = 0
17 sort: SortMeta = { field: 'createdAt', order: -1 }
18 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
19
20 constructor (
21 private notifier: Notifier,
22 private blocklistService: BlocklistService,
23 private i18n: I18n
24 ) {
25 super()
26 }
27
28 ngOnInit () {
29 this.initialize()
30 }
31 11
32 getIdentifier () { 12 getIdentifier () {
33 return 'InstanceAccountBlocklistComponent' 13 return 'InstanceAccountBlocklistComponent'
34 } 14 }
35
36 switchToDefaultAvatar ($event: Event) {
37 ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
38 }
39
40 unblockAccount (accountBlock: AccountBlock) {
41 const blockedAccount = accountBlock.blockedAccount
42
43 this.blocklistService.unblockAccountByInstance(blockedAccount)
44 .subscribe(
45 () => {
46 this.notifier.success(
47 this.i18n('Account {{nameWithHost}} unmuted by your instance.', { nameWithHost: blockedAccount.nameWithHost })
48 )
49
50 this.loadData()
51 }
52 )
53 }
54
55 protected loadData () {
56 return this.blocklistService.getInstanceAccountBlocklist({
57 pagination: this.pagination,
58 sort: this.sort,
59 search: this.search
60 })
61 .subscribe(
62 resultList => {
63 this.blockedAccounts = resultList.data
64 this.totalRecords = resultList.total
65 },
66
67 err => this.notifier.error(err.message)
68 )
69 }
70} 15}
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
index 559c9c0b0..9d4ec174a 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.ts
@@ -1,84 +1,15 @@
1import { Component, OnInit, ViewChild } from '@angular/core' 1import { Component } from '@angular/core'
2import { Notifier } from '@app/core' 2import { GenericServerBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/api'
6import { BlocklistService } from '@app/shared/blocklist'
7import { ServerBlock } from '../../../../../../shared'
8import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component'
9 3
10@Component({ 4@Component({
11 selector: 'my-instance-server-blocklist', 5 selector: 'my-instance-server-blocklist',
12 styleUrls: [ '../moderation.component.scss', './instance-server-blocklist.component.scss' ], 6 styleUrls: [ '../../../shared/blocklist/server-blocklist.component.scss' ],
13 templateUrl: './instance-server-blocklist.component.html' 7 templateUrl: '../../../shared/blocklist/server-blocklist.component.html'
14}) 8})
15export class InstanceServerBlocklistComponent extends RestTable implements OnInit { 9export class InstanceServerBlocklistComponent extends GenericServerBlocklistComponent {
16 @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent 10 mode = BlocklistComponentType.Instance
17
18 blockedServers: ServerBlock[] = []
19 totalRecords = 0
20 sort: SortMeta = { field: 'createdAt', order: -1 }
21 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
22
23 constructor (
24 private notifier: Notifier,
25 private blocklistService: BlocklistService,
26 private i18n: I18n
27 ) {
28 super()
29 }
30
31 ngOnInit () {
32 this.initialize()
33 }
34 11
35 getIdentifier () { 12 getIdentifier () {
36 return 'InstanceServerBlocklistComponent' 13 return 'InstanceServerBlocklistComponent'
37 } 14 }
38
39 unblockServer (serverBlock: ServerBlock) {
40 const host = serverBlock.blockedServer.host
41
42 this.blocklistService.unblockServerByInstance(host)
43 .subscribe(
44 () => {
45 this.notifier.success(this.i18n('Instance {{host}} unmuted by your instance.', { host }))
46
47 this.loadData()
48 }
49 )
50 }
51
52 addServersToBlock () {
53 this.batchDomainsModal.openModal()
54 }
55
56 onDomainsToBlock (domains: string[]) {
57 domains.forEach(domain => {
58 this.blocklistService.blockServerByInstance(domain)
59 .subscribe(
60 () => {
61 this.notifier.success(this.i18n('Instance {{domain}} muted by your instance.', { domain }))
62
63 this.loadData()
64 }
65 )
66 })
67 }
68
69 protected loadData () {
70 return this.blocklistService.getInstanceServerBlocklist({
71 pagination: this.pagination,
72 sort: this.sort,
73 search: this.search
74 })
75 .subscribe(
76 resultList => {
77 this.blockedServers = resultList.data
78 this.totalRecords = resultList.total
79 },
80
81 err => this.notifier.error(err.message)
82 )
83 }
84} 15}
diff --git a/client/src/app/+admin/moderation/moderation.component.scss b/client/src/app/+admin/moderation/moderation.component.scss
index 404eb0504..ba68cf6f6 100644
--- a/client/src/app/+admin/moderation/moderation.component.scss
+++ b/client/src/app/+admin/moderation/moderation.component.scss
@@ -16,10 +16,6 @@
16 } 16 }
17} 17}
18 18
19.empty-table-message {
20 @include empty-state;
21}
22
23.moderation-expanded { 19.moderation-expanded {
24 font-size: 90%; 20 font-size: 90%;
25 21
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
index a2ed51559..64641b28a 100644
--- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
+++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html
@@ -137,7 +137,7 @@
137 <ng-template pTemplate="emptymessage"> 137 <ng-template pTemplate="emptymessage">
138 <tr> 138 <tr>
139 <td colspan="6"> 139 <td colspan="6">
140 <div class="empty-table-message"> 140 <div class="no-results">
141 <ng-container *ngIf="search" i18n>No video abuses found matching current filters.</ng-container> 141 <ng-container *ngIf="search" i18n>No video abuses found matching current filters.</ng-container>
142 <ng-container *ngIf="!search" i18n>No video abuses found.</ng-container> 142 <ng-container *ngIf="!search" i18n>No video abuses found.</ng-container>
143 </div> 143 </div>
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
index a01a2566d..ec20e46f1 100644
--- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
+++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
@@ -102,7 +102,7 @@
102 <ng-template pTemplate="emptymessage"> 102 <ng-template pTemplate="emptymessage">
103 <tr> 103 <tr>
104 <td colspan="6"> 104 <td colspan="6">
105 <div class="empty-table-message"> 105 <div class="no-results">
106 <ng-container *ngIf="search" i18n>No blocked video found matching current filters.</ng-container> 106 <ng-container *ngIf="search" i18n>No blocked video found matching current filters.</ng-container>
107 <ng-container *ngIf="!search" i18n>No blocked video found.</ng-container> 107 <ng-container *ngIf="!search" i18n>No blocked video found.</ng-container>
108 </div> 108 </div>
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.html b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.html
deleted file mode 100644
index 90f657521..000000000
--- a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.html
+++ /dev/null
@@ -1,27 +0,0 @@
1<div class="admin-sub-header">
2 <h1 i18n class="form-sub-title">Muted accounts</h1>
3</div>
4
5<p-table
6 [value]="blockedAccounts" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage"
7 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
8>
9
10 <ng-template pTemplate="header">
11 <tr>
12 <th i18n>Account</th>
13 <th i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
14 <th></th> <!-- column for action buttons -->
15 </tr>
16 </ng-template>
17
18 <ng-template pTemplate="body" let-accountBlock>
19 <tr>
20 <td>{{ accountBlock.blockedAccount.nameWithHost }}</td>
21 <td>{{ accountBlock.createdAt }}</td>
22 <td class="action-cell">
23 <button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
24 </td>
25 </tr>
26 </ng-template>
27</p-table>
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.scss b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.scss
deleted file mode 100644
index 6028b75ea..000000000
--- a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
1@import '_variables';
2@import '_mixins';
3
4.unblock-button {
5 @include peertube-button;
6 @include grey-button;
7} \ No newline at end of file
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
index fd1fabcdb..e48c39cdf 100644
--- a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
+++ b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
@@ -1,59 +1,15 @@
1import { Component, OnInit } from '@angular/core' 1import { Component } from '@angular/core'
2import { Notifier } from '@app/core' 2import { GenericAccountBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/api'
6import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
7 3
8@Component({ 4@Component({
9 selector: 'my-account-blocklist', 5 selector: 'my-account-blocklist',
10 styleUrls: [ './my-account-blocklist.component.scss' ], 6 styleUrls: [ '../../shared/blocklist/account-blocklist.component.scss' ],
11 templateUrl: './my-account-blocklist.component.html' 7 templateUrl: '../../shared/blocklist/account-blocklist.component.html'
12}) 8})
13export class MyAccountBlocklistComponent extends RestTable implements OnInit { 9export class MyAccountBlocklistComponent extends GenericAccountBlocklistComponent {
14 blockedAccounts: AccountBlock[] = [] 10 mode = BlocklistComponentType.Account
15 totalRecords = 0
16 sort: SortMeta = { field: 'createdAt', order: -1 }
17 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
18
19 constructor (
20 private notifier: Notifier,
21 private blocklistService: BlocklistService,
22 private i18n: I18n
23 ) {
24 super()
25 }
26
27 ngOnInit () {
28 this.initialize()
29 }
30 11
31 getIdentifier () { 12 getIdentifier () {
32 return 'MyAccountBlocklistComponent' 13 return 'MyAccountBlocklistComponent'
33 } 14 }
34
35 unblockAccount (accountBlock: AccountBlock) {
36 const blockedAccount = accountBlock.blockedAccount
37
38 this.blocklistService.unblockAccountByUser(blockedAccount)
39 .subscribe(
40 () => {
41 this.notifier.success(this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost }))
42
43 this.loadData()
44 }
45 )
46 }
47
48 protected loadData () {
49 return this.blocklistService.getUserAccountBlocklist(this.pagination, this.sort)
50 .subscribe(
51 resultList => {
52 this.blockedAccounts = resultList.data
53 this.totalRecords = resultList.total
54 },
55
56 err => this.notifier.error(err.message)
57 )
58 }
59} 15}
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.html b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.html
deleted file mode 100644
index c31cff16f..000000000
--- a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.html
+++ /dev/null
@@ -1,27 +0,0 @@
1<div class="admin-sub-header">
2 <h1 i18n class="form-sub-title">Muted instances</h1>
3</div>
4
5<p-table
6 [value]="blockedServers" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage"
7 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
8>
9
10 <ng-template pTemplate="header">
11 <tr>
12 <th i18n>Instance</th>
13 <th i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
14 <th></th> <!-- column for action buttons -->
15 </tr>
16 </ng-template>
17
18 <ng-template pTemplate="body" let-serverBlock>
19 <tr>
20 <td>{{ serverBlock.blockedServer.host }}</td>
21 <td>{{ serverBlock.createdAt }}</td>
22 <td class="action-cell">
23 <button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button>
24 </td>
25 </tr>
26 </ng-template>
27</p-table>
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.scss b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.scss
deleted file mode 100644
index 6028b75ea..000000000
--- a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
1@import '_variables';
2@import '_mixins';
3
4.unblock-button {
5 @include peertube-button;
6 @include grey-button;
7} \ No newline at end of file
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
index 483c11804..cfaba1c7b 100644
--- a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
+++ b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
@@ -1,60 +1,15 @@
1import { Component, OnInit } from '@angular/core' 1import { Component } from '@angular/core'
2import { Notifier } from '@app/core' 2import { GenericServerBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/api'
6import { ServerBlock } from '../../../../../shared'
7import { BlocklistService } from '@app/shared/blocklist'
8 3
9@Component({ 4@Component({
10 selector: 'my-account-server-blocklist', 5 selector: 'my-account-server-blocklist',
11 styleUrls: [ './my-account-server-blocklist.component.scss' ], 6 styleUrls: [ '../../+admin/moderation/moderation.component.scss', '../../shared/blocklist/server-blocklist.component.scss' ],
12 templateUrl: './my-account-server-blocklist.component.html' 7 templateUrl: '../../shared/blocklist/server-blocklist.component.html'
13}) 8})
14export class MyAccountServerBlocklistComponent extends RestTable implements OnInit { 9export class MyAccountServerBlocklistComponent extends GenericServerBlocklistComponent {
15 blockedServers: ServerBlock[] = [] 10 mode = BlocklistComponentType.Account
16 totalRecords = 0
17 sort: SortMeta = { field: 'createdAt', order: -1 }
18 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
19
20 constructor (
21 private notifier: Notifier,
22 private blocklistService: BlocklistService,
23 private i18n: I18n
24 ) {
25 super()
26 }
27
28 ngOnInit () {
29 this.initialize()
30 }
31 11
32 getIdentifier () { 12 getIdentifier () {
33 return 'MyAccountServerBlocklistComponent' 13 return 'MyAccountServerBlocklistComponent'
34 } 14 }
35
36 unblockServer (serverBlock: ServerBlock) {
37 const host = serverBlock.blockedServer.host
38
39 this.blocklistService.unblockServerByUser(host)
40 .subscribe(
41 () => {
42 this.notifier.success(this.i18n('Instance {{host}} unmuted.', { host }))
43
44 this.loadData()
45 }
46 )
47 }
48
49 protected loadData () {
50 return this.blocklistService.getUserServerBlocklist(this.pagination, this.sort)
51 .subscribe(
52 resultList => {
53 this.blockedServers = resultList.data
54 this.totalRecords = resultList.total
55 },
56
57 err => this.notifier.error(err.message)
58 )
59 }
60} 15}
diff --git a/client/src/app/+my-account/my-account-routing.module.ts b/client/src/app/+my-account/my-account-routing.module.ts
index f44b60ec9..f6b711e09 100644
--- a/client/src/app/+my-account/my-account-routing.module.ts
+++ b/client/src/app/+my-account/my-account-routing.module.ts
@@ -140,7 +140,7 @@ const myAccountRoutes: Routes = [
140 component: MyAccountServerBlocklistComponent, 140 component: MyAccountServerBlocklistComponent,
141 data: { 141 data: {
142 meta: { 142 meta: {
143 title: 'Muted instances' 143 title: 'Muted servers'
144 } 144 }
145 } 145 }
146 }, 146 },
diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts
index 05dcf522d..ca447c054 100644
--- a/client/src/app/+my-account/my-account.component.ts
+++ b/client/src/app/+my-account/my-account.component.ts
@@ -72,7 +72,7 @@ export class MyAccountComponent implements OnInit {
72 iconName: 'user' 72 iconName: 'user'
73 }, 73 },
74 { 74 {
75 label: this.i18n('Muted instances'), 75 label: this.i18n('Muted servers'),
76 routerLink: '/my-account/blocklist/servers', 76 routerLink: '/my-account/blocklist/servers',
77 iconName: 'server' 77 iconName: 'server'
78 }, 78 },
diff --git a/client/src/app/shared/blocklist/account-blocklist.component.html b/client/src/app/shared/blocklist/account-blocklist.component.html
new file mode 100644
index 000000000..486785f35
--- /dev/null
+++ b/client/src/app/shared/blocklist/account-blocklist.component.html
@@ -0,0 +1,64 @@
1<p-table
2 [value]="blockedAccounts" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
3 [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
4 [showCurrentPageReport]="true" i18n-currentPageReportTemplate
5 currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
6>
7 <ng-template pTemplate="caption">
8 <div class="caption">
9 <div class="ml-auto has-feedback has-clear">
10 <input
11 type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
12 (keyup)="onSearch($event)"
13 >
14 <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
15 <span class="sr-only" i18n>Clear filters</span>
16 </div>
17 </div>
18 </ng-template>
19
20 <ng-template pTemplate="header">
21 <tr>
22 <th style="width: 100%;" i18n>Account</th>
23 <th style="width: 150px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
24 <th style="width: 150px;"></th> <!-- column for action buttons -->
25 </tr>
26 </ng-template>
27
28 <ng-template pTemplate="body" let-accountBlock>
29 <tr>
30 <td>
31 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
32 <div class="chip two-lines">
33 <img
34 class="avatar"
35 [src]="accountBlock.blockedAccount.avatar?.path"
36 (error)="switchToDefaultAvatar($event)"
37 alt="Avatar"
38 >
39 <div>
40 {{ accountBlock.blockedAccount.displayName }}
41 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span>
42 </div>
43 </div>
44 </a>
45 </td>
46
47 <td>{{ accountBlock.createdAt | date: 'short' }}</td>
48 <td class="action-cell">
49 <button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
50 </td>
51 </tr>
52 </ng-template>
53
54 <ng-template pTemplate="emptymessage">
55 <tr>
56 <td colspan="6">
57 <div class="no-results">
58 <ng-container *ngIf="search" i18n>No account found matching current filters.</ng-container>
59 <ng-container *ngIf="!search" i18n>No account found.</ng-container>
60 </div>
61 </td>
62 </tr>
63 </ng-template>
64</p-table>
diff --git a/client/src/app/shared/blocklist/account-blocklist.component.scss b/client/src/app/shared/blocklist/account-blocklist.component.scss
new file mode 100644
index 000000000..aa8363ff4
--- /dev/null
+++ b/client/src/app/shared/blocklist/account-blocklist.component.scss
@@ -0,0 +1,16 @@
1@import '_variables';
2@import '_mixins';
3
4.caption {
5 justify-content: flex-end;
6
7 input {
8 @include peertube-input-text(250px);
9 flex-grow: 1;
10 }
11}
12
13.unblock-button {
14 @include peertube-button;
15 @include grey-button;
16} \ No newline at end of file
diff --git a/client/src/app/shared/blocklist/account-blocklist.component.ts b/client/src/app/shared/blocklist/account-blocklist.component.ts
new file mode 100644
index 000000000..dc5ac4044
--- /dev/null
+++ b/client/src/app/shared/blocklist/account-blocklist.component.ts
@@ -0,0 +1,79 @@
1import { OnInit } from '@angular/core'
2import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared/rest'
5import { SortMeta } from 'primeng/api'
6import { AccountBlock } from './account-block.model'
7import { BlocklistService, BlocklistComponentType } from './blocklist.service'
8import { Actor } from '@app/shared/actor/actor.model'
9
10export class GenericAccountBlocklistComponent extends RestTable implements OnInit {
11 // @ts-ignore: "Abstract methods can only appear within an abstract class"
12 abstract mode: BlocklistComponentType
13
14 blockedAccounts: AccountBlock[] = []
15 totalRecords = 0
16 sort: SortMeta = { field: 'createdAt', order: -1 }
17 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
18
19 constructor (
20 private notifier: Notifier,
21 private blocklistService: BlocklistService,
22 private i18n: I18n
23 ) {
24 super()
25 }
26
27 // @ts-ignore: "Abstract methods can only appear within an abstract class"
28 abstract getIdentifier (): string
29
30 ngOnInit () {
31 this.initialize()
32 }
33
34 switchToDefaultAvatar ($event: Event) {
35 ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
36 }
37
38 unblockAccount (accountBlock: AccountBlock) {
39 const blockedAccount = accountBlock.blockedAccount
40 const operation = this.mode === BlocklistComponentType.Account
41 ? this.blocklistService.unblockAccountByUser(blockedAccount)
42 : this.blocklistService.unblockAccountByInstance(blockedAccount)
43
44 operation.subscribe(
45 () => {
46 this.notifier.success(
47 this.mode === BlocklistComponentType.Account
48 ? this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost })
49 : this.i18n('Account {{nameWithHost}} unmuted by your instance.', { nameWithHost: blockedAccount.nameWithHost })
50 )
51
52 this.loadData()
53 }
54 )
55 }
56
57 protected loadData () {
58 const operation = this.mode === BlocklistComponentType.Account
59 ? this.blocklistService.getUserAccountBlocklist({
60 pagination: this.pagination,
61 sort: this.sort,
62 search: this.search
63 })
64 : this.blocklistService.getInstanceAccountBlocklist({
65 pagination: this.pagination,
66 sort: this.sort,
67 search: this.search
68 })
69
70 return operation.subscribe(
71 resultList => {
72 this.blockedAccounts = resultList.data
73 this.totalRecords = resultList.total
74 },
75
76 err => this.notifier.error(err.message)
77 )
78 }
79}
diff --git a/client/src/app/shared/blocklist/blocklist.service.ts b/client/src/app/shared/blocklist/blocklist.service.ts
index 5cf265bc1..c70a8173a 100644
--- a/client/src/app/shared/blocklist/blocklist.service.ts
+++ b/client/src/app/shared/blocklist/blocklist.service.ts
@@ -8,6 +8,8 @@ import { AccountBlock as AccountBlockServer, ResultList, ServerBlock } from '../
8import { Account } from '@app/shared/account/account.model' 8import { Account } from '@app/shared/account/account.model'
9import { AccountBlock } from '@app/shared/blocklist/account-block.model' 9import { AccountBlock } from '@app/shared/blocklist/account-block.model'
10 10
11export enum BlocklistComponentType { Account, Instance }
12
11@Injectable() 13@Injectable()
12export class BlocklistService { 14export class BlocklistService {
13 static BASE_USER_BLOCKLIST_URL = environment.apiUrl + '/api/v1/users/me/blocklist' 15 static BASE_USER_BLOCKLIST_URL = environment.apiUrl + '/api/v1/users/me/blocklist'
@@ -21,10 +23,14 @@ export class BlocklistService {
21 23
22 /*********************** User -> Account blocklist ***********************/ 24 /*********************** User -> Account blocklist ***********************/
23 25
24 getUserAccountBlocklist (pagination: RestPagination, sort: SortMeta) { 26 getUserAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
27 const { pagination, sort, search } = options
28
25 let params = new HttpParams() 29 let params = new HttpParams()
26 params = this.restService.addRestGetParams(params, pagination, sort) 30 params = this.restService.addRestGetParams(params, pagination, sort)
27 31
32 if (search) params = params.append('search', search)
33
28 return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', { params }) 34 return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', { params })
29 .pipe( 35 .pipe(
30 map(res => this.restExtractor.convertResultListDateToHuman(res)), 36 map(res => this.restExtractor.convertResultListDateToHuman(res)),
@@ -49,10 +55,14 @@ export class BlocklistService {
49 55
50 /*********************** User -> Server blocklist ***********************/ 56 /*********************** User -> Server blocklist ***********************/
51 57
52 getUserServerBlocklist (pagination: RestPagination, sort: SortMeta) { 58 getUserServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
59 const { pagination, sort, search } = options
60
53 let params = new HttpParams() 61 let params = new HttpParams()
54 params = this.restService.addRestGetParams(params, pagination, sort) 62 params = this.restService.addRestGetParams(params, pagination, sort)
55 63
64 if (search) params = params.append('search', search)
65
56 return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers', { params }) 66 return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers', { params })
57 .pipe( 67 .pipe(
58 map(res => this.restExtractor.convertResultListDateToHuman(res)), 68 map(res => this.restExtractor.convertResultListDateToHuman(res)),
@@ -76,7 +86,7 @@ export class BlocklistService {
76 86
77 /*********************** Instance -> Account blocklist ***********************/ 87 /*********************** Instance -> Account blocklist ***********************/
78 88
79 getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) { 89 getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
80 const { pagination, sort, search } = options 90 const { pagination, sort, search } = options
81 91
82 let params = new HttpParams() 92 let params = new HttpParams()
@@ -108,7 +118,7 @@ export class BlocklistService {
108 118
109 /*********************** Instance -> Server blocklist ***********************/ 119 /*********************** Instance -> Server blocklist ***********************/
110 120
111 getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) { 121 getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
112 const { pagination, sort, search } = options 122 const { pagination, sort, search } = options
113 123
114 let params = new HttpParams() 124 let params = new HttpParams()
diff --git a/client/src/app/shared/blocklist/index.ts b/client/src/app/shared/blocklist/index.ts
index 5886ca07e..188057b19 100644
--- a/client/src/app/shared/blocklist/index.ts
+++ b/client/src/app/shared/blocklist/index.ts
@@ -1,2 +1,4 @@
1export * from './blocklist.service' 1export * from './blocklist.service'
2export * from './account-block.model' 2export * from './account-block.model'
3export * from './server-blocklist.component'
4export * from './account-blocklist.component'
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html b/client/src/app/shared/blocklist/server-blocklist.component.html
index 7a77b8842..977e0e141 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html
+++ b/client/src/app/shared/blocklist/server-blocklist.component.html
@@ -47,7 +47,7 @@
47 <ng-template pTemplate="emptymessage"> 47 <ng-template pTemplate="emptymessage">
48 <tr> 48 <tr>
49 <td colspan="6"> 49 <td colspan="6">
50 <div class="empty-table-message"> 50 <div class="no-results">
51 <ng-container *ngIf="search" i18n>No server found matching current filters.</ng-container> 51 <ng-container *ngIf="search" i18n>No server found matching current filters.</ng-container>
52 <ng-container *ngIf="!search" i18n>No server found.</ng-container> 52 <ng-container *ngIf="!search" i18n>No server found.</ng-container>
53 </div> 53 </div>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss b/client/src/app/shared/blocklist/server-blocklist.component.scss
index c1f66116b..9ddb76850 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss
+++ b/client/src/app/shared/blocklist/server-blocklist.component.scss
@@ -15,6 +15,15 @@ a {
15 } 15 }
16} 16}
17 17
18.caption {
19 justify-content: flex-end;
20
21 input {
22 @include peertube-input-text(250px);
23 flex-grow: 1;
24 }
25}
26
18.unblock-button { 27.unblock-button {
19 @include peertube-button; 28 @include peertube-button;
20 @include grey-button; 29 @include grey-button;
diff --git a/client/src/app/shared/blocklist/server-blocklist.component.ts b/client/src/app/shared/blocklist/server-blocklist.component.ts
new file mode 100644
index 000000000..f2b36badc
--- /dev/null
+++ b/client/src/app/shared/blocklist/server-blocklist.component.ts
@@ -0,0 +1,101 @@
1import { OnInit, ViewChild } from '@angular/core'
2import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared/rest'
5import { SortMeta } from 'primeng/api'
6import { BlocklistService, BlocklistComponentType } from './blocklist.service'
7import { ServerBlock } from '../../../../../shared/models/blocklist/server-block.model'
8import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component'
9
10export class GenericServerBlocklistComponent extends RestTable implements OnInit {
11 @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent
12
13 // @ts-ignore: "Abstract methods can only appear within an abstract class"
14 public abstract mode: BlocklistComponentType
15
16 blockedServers: ServerBlock[] = []
17 totalRecords = 0
18 sort: SortMeta = { field: 'createdAt', order: -1 }
19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
20
21 constructor (
22 protected notifier: Notifier,
23 protected blocklistService: BlocklistService,
24 protected i18n: I18n
25 ) {
26 super()
27 }
28
29 ngOnInit () {
30 this.initialize()
31 }
32
33 // @ts-ignore: "Abstract methods can only appear within an abstract class"
34 public abstract getIdentifier (): string
35
36 unblockServer (serverBlock: ServerBlock) {
37 const operation = (host: string) => this.mode === BlocklistComponentType.Account
38 ? this.blocklistService.unblockServerByUser(host)
39 : this.blocklistService.unblockServerByInstance(host)
40 const host = serverBlock.blockedServer.host
41
42 operation(host).subscribe(
43 () => {
44 this.notifier.success(
45 this.mode === BlocklistComponentType.Account
46 ? this.i18n('Instance {{host}} unmuted.', { host })
47 : this.i18n('Instance {{host}} unmuted by your instance.', { host })
48 )
49
50 this.loadData()
51 }
52 )
53 }
54
55 addServersToBlock () {
56 this.batchDomainsModal.openModal()
57 }
58
59 onDomainsToBlock (domains: string[]) {
60 const operation = (domain: string) => this.mode === BlocklistComponentType.Account
61 ? this.blocklistService.blockServerByUser(domain)
62 : this.blocklistService.blockServerByInstance(domain)
63
64 domains.forEach(domain => {
65 operation(domain).subscribe(
66 () => {
67 this.notifier.success(
68 this.mode === BlocklistComponentType.Account
69 ? this.i18n('Instance {{domain}} muted.', { domain })
70 : this.i18n('Instance {{domain}} muted by your instance.', { domain })
71 )
72
73 this.loadData()
74 }
75 )
76 })
77 }
78
79 protected loadData () {
80 const operation = this.mode === BlocklistComponentType.Account
81 ? this.blocklistService.getUserServerBlocklist({
82 pagination: this.pagination,
83 sort: this.sort,
84 search: this.search
85 })
86 : this.blocklistService.getInstanceServerBlocklist({
87 pagination: this.pagination,
88 sort: this.sort,
89 search: this.search
90 })
91
92 return operation.subscribe(
93 resultList => {
94 this.blockedServers = resultList.data
95 this.totalRecords = resultList.total
96 },
97
98 err => this.notifier.error(err.message)
99 )
100 }
101}
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index 2035097d7..98fab9e16 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -10,6 +10,7 @@ import { NgModule } from '@angular/core'
10import { FormsModule, ReactiveFormsModule } from '@angular/forms' 10import { FormsModule, ReactiveFormsModule } from '@angular/forms'
11import { RouterModule } from '@angular/router' 11import { RouterModule } from '@angular/router'
12import { BatchDomainsValidatorsService } from '@app/+admin/config/shared/batch-domains-validators.service' 12import { BatchDomainsValidatorsService } from '@app/+admin/config/shared/batch-domains-validators.service'
13import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component'
13import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface' 14import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface'
14import { MyAccountVideoSettingsComponent } from '@app/+my-account/my-account-settings/my-account-video-settings' 15import { MyAccountVideoSettingsComponent } from '@app/+my-account/my-account-settings/my-account-video-settings'
15import { ActorAvatarInfoComponent } from '@app/+my-account/shared/actor-avatar-info.component' 16import { ActorAvatarInfoComponent } from '@app/+my-account/shared/actor-avatar-info.component'
@@ -192,7 +193,8 @@ import { VideoService } from './video/video.service'
192 193
193 MyAccountVideoSettingsComponent, 194 MyAccountVideoSettingsComponent,
194 MyAccountInterfaceSettingsComponent, 195 MyAccountInterfaceSettingsComponent,
195 ActorAvatarInfoComponent 196 ActorAvatarInfoComponent,
197 BatchDomainsModalComponent
196 ], 198 ],
197 199
198 exports: [ 200 exports: [
@@ -274,7 +276,8 @@ import { VideoService } from './video/video.service'
274 276
275 MyAccountVideoSettingsComponent, 277 MyAccountVideoSettingsComponent,
276 MyAccountInterfaceSettingsComponent, 278 MyAccountInterfaceSettingsComponent,
277 ActorAvatarInfoComponent 279 ActorAvatarInfoComponent,
280 BatchDomainsModalComponent
278 ], 281 ],
279 282
280 providers: [ 283 providers: [
diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss
index aaa1c05bd..4f753e041 100644
--- a/client/src/sass/application.scss
+++ b/client/src/sass/application.scss
@@ -258,6 +258,8 @@ table {
258 258
259.no-results { 259.no-results {
260 height: 40vh; 260 height: 40vh;
261 max-height: 500px;
262
261 display: flex; 263 display: flex;
262 align-items: center; 264 align-items: center;
263 justify-content: center; 265 justify-content: center;
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss
index 5971bb72a..eb80ea0e3 100644
--- a/client/src/sass/include/_mixins.scss
+++ b/client/src/sass/include/_mixins.scss
@@ -856,15 +856,6 @@
856 } 856 }
857} 857}
858 858
859@mixin empty-state {
860 min-height: 40vh;
861 max-height: 500px;
862
863 display: flex;
864 justify-content: center;
865 align-items: center;
866}
867
868@mixin admin-sub-header-responsive ($horizontal-margins) { 859@mixin admin-sub-header-responsive ($horizontal-margins) {
869 flex-direction: column; 860 flex-direction: column;
870 861