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' import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' import { VideoRedundancyInformationComponent } from '@app/+admin/follows/video-redundancies-list/video-redundancy-information.component' import { ChartModule } from 'primeng/chart' -import { BatchDomainsModalComponent } from './config/shared/batch-domains-modal.component' import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video-abuse-details.component' @NgModule({ @@ -76,9 +75,7 @@ import { VideoAbuseDetailsComponent } from './moderation/video-abuse-list/video- DebugComponent, ConfigComponent, - EditCustomConfigComponent, - - BatchDomainsModalComponent + EditCustomConfigComponent ], 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 @@ -
+
No follower found matching current filters. Your instance doesn't have any follower.
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 @@ -
+
No host found matching current filters. Your instance is not following anyone.
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 @@ flex-grow: 0; margin-right: 30px; } - -.empty-table-message { - @include empty-state; -} 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 @@ -
+
Your instance doesn't mirror any video. Your instance has no mirrored videos.
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 @@ -
+
No account found matching current filters. No account found.
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 @@ -import { Component, OnInit } from '@angular/core' -import { Notifier } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { RestPagination, RestTable } from '@app/shared' -import { SortMeta } from 'primeng/api' -import { AccountBlock, BlocklistService } from '@app/shared/blocklist' -import { Actor } from '@app/shared/actor/actor.model' +import { Component } from '@angular/core' +import { GenericAccountBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist' @Component({ selector: 'my-instance-account-blocklist', - styleUrls: [ '../moderation.component.scss', './instance-account-blocklist.component.scss' ], - templateUrl: './instance-account-blocklist.component.html' + styleUrls: [ '../moderation.component.scss', '../../../shared/blocklist/account-blocklist.component.scss' ], + templateUrl: '../../../shared/blocklist/account-blocklist.component.html' }) -export class InstanceAccountBlocklistComponent extends RestTable implements OnInit { - blockedAccounts: AccountBlock[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: -1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - - constructor ( - private notifier: Notifier, - private blocklistService: BlocklistService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.initialize() - } +export class InstanceAccountBlocklistComponent extends GenericAccountBlocklistComponent { + mode = BlocklistComponentType.Instance getIdentifier () { return 'InstanceAccountBlocklistComponent' } - - switchToDefaultAvatar ($event: Event) { - ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL() - } - - unblockAccount (accountBlock: AccountBlock) { - const blockedAccount = accountBlock.blockedAccount - - this.blocklistService.unblockAccountByInstance(blockedAccount) - .subscribe( - () => { - this.notifier.success( - this.i18n('Account {{nameWithHost}} unmuted by your instance.', { nameWithHost: blockedAccount.nameWithHost }) - ) - - this.loadData() - } - ) - } - - protected loadData () { - return this.blocklistService.getInstanceAccountBlocklist({ - pagination: this.pagination, - sort: this.sort, - search: this.search - }) - .subscribe( - resultList => { - this.blockedAccounts = resultList.data - this.totalRecords = resultList.total - }, - - err => this.notifier.error(err.message) - ) - } } 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 @@ -import { Component, OnInit, ViewChild } from '@angular/core' -import { Notifier } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { RestPagination, RestTable } from '@app/shared' -import { SortMeta } from 'primeng/api' -import { BlocklistService } from '@app/shared/blocklist' -import { ServerBlock } from '../../../../../../shared' -import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component' +import { Component } from '@angular/core' +import { GenericServerBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist' @Component({ selector: 'my-instance-server-blocklist', - styleUrls: [ '../moderation.component.scss', './instance-server-blocklist.component.scss' ], - templateUrl: './instance-server-blocklist.component.html' + styleUrls: [ '../../../shared/blocklist/server-blocklist.component.scss' ], + templateUrl: '../../../shared/blocklist/server-blocklist.component.html' }) -export class InstanceServerBlocklistComponent extends RestTable implements OnInit { - @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent - - blockedServers: ServerBlock[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: -1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - - constructor ( - private notifier: Notifier, - private blocklistService: BlocklistService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.initialize() - } +export class InstanceServerBlocklistComponent extends GenericServerBlocklistComponent { + mode = BlocklistComponentType.Instance getIdentifier () { return 'InstanceServerBlocklistComponent' } - - unblockServer (serverBlock: ServerBlock) { - const host = serverBlock.blockedServer.host - - this.blocklistService.unblockServerByInstance(host) - .subscribe( - () => { - this.notifier.success(this.i18n('Instance {{host}} unmuted by your instance.', { host })) - - this.loadData() - } - ) - } - - addServersToBlock () { - this.batchDomainsModal.openModal() - } - - onDomainsToBlock (domains: string[]) { - domains.forEach(domain => { - this.blocklistService.blockServerByInstance(domain) - .subscribe( - () => { - this.notifier.success(this.i18n('Instance {{domain}} muted by your instance.', { domain })) - - this.loadData() - } - ) - }) - } - - protected loadData () { - return this.blocklistService.getInstanceServerBlocklist({ - pagination: this.pagination, - sort: this.sort, - search: this.search - }) - .subscribe( - resultList => { - this.blockedServers = resultList.data - this.totalRecords = resultList.total - }, - - err => this.notifier.error(err.message) - ) - } } 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 @@ } } -.empty-table-message { - @include empty-state; -} - .moderation-expanded { font-size: 90%; 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 @@ -
+
No video abuses found matching current filters. No video abuses found.
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 @@ -
+
No blocked video found matching current filters. No blocked video found.
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 @@ -
-

Muted accounts

-
- - - - - - Account - Muted at - - - - - - - {{ accountBlock.blockedAccount.nameWithHost }} - {{ accountBlock.createdAt }} - - - - - - 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 @@ -@import '_variables'; -@import '_mixins'; - -.unblock-button { - @include peertube-button; - @include grey-button; -} \ 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 @@ -import { Component, OnInit } from '@angular/core' -import { Notifier } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { RestPagination, RestTable } from '@app/shared' -import { SortMeta } from 'primeng/api' -import { AccountBlock, BlocklistService } from '@app/shared/blocklist' +import { Component } from '@angular/core' +import { GenericAccountBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist' @Component({ selector: 'my-account-blocklist', - styleUrls: [ './my-account-blocklist.component.scss' ], - templateUrl: './my-account-blocklist.component.html' + styleUrls: [ '../../shared/blocklist/account-blocklist.component.scss' ], + templateUrl: '../../shared/blocklist/account-blocklist.component.html' }) -export class MyAccountBlocklistComponent extends RestTable implements OnInit { - blockedAccounts: AccountBlock[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: -1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - - constructor ( - private notifier: Notifier, - private blocklistService: BlocklistService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.initialize() - } +export class MyAccountBlocklistComponent extends GenericAccountBlocklistComponent { + mode = BlocklistComponentType.Account getIdentifier () { return 'MyAccountBlocklistComponent' } - - unblockAccount (accountBlock: AccountBlock) { - const blockedAccount = accountBlock.blockedAccount - - this.blocklistService.unblockAccountByUser(blockedAccount) - .subscribe( - () => { - this.notifier.success(this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost })) - - this.loadData() - } - ) - } - - protected loadData () { - return this.blocklistService.getUserAccountBlocklist(this.pagination, this.sort) - .subscribe( - resultList => { - this.blockedAccounts = resultList.data - this.totalRecords = resultList.total - }, - - err => this.notifier.error(err.message) - ) - } } 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 @@ -
-

Muted instances

-
- - - - - - Instance - Muted at - - - - - - - {{ serverBlock.blockedServer.host }} - {{ serverBlock.createdAt }} - - - - - - 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 @@ -@import '_variables'; -@import '_mixins'; - -.unblock-button { - @include peertube-button; - @include grey-button; -} \ 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 @@ -import { Component, OnInit } from '@angular/core' -import { Notifier } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { RestPagination, RestTable } from '@app/shared' -import { SortMeta } from 'primeng/api' -import { ServerBlock } from '../../../../../shared' -import { BlocklistService } from '@app/shared/blocklist' +import { Component } from '@angular/core' +import { GenericServerBlocklistComponent, BlocklistComponentType } from '@app/shared/blocklist' @Component({ selector: 'my-account-server-blocklist', - styleUrls: [ './my-account-server-blocklist.component.scss' ], - templateUrl: './my-account-server-blocklist.component.html' + styleUrls: [ '../../+admin/moderation/moderation.component.scss', '../../shared/blocklist/server-blocklist.component.scss' ], + templateUrl: '../../shared/blocklist/server-blocklist.component.html' }) -export class MyAccountServerBlocklistComponent extends RestTable implements OnInit { - blockedServers: ServerBlock[] = [] - totalRecords = 0 - sort: SortMeta = { field: 'createdAt', order: -1 } - pagination: RestPagination = { count: this.rowsPerPage, start: 0 } - - constructor ( - private notifier: Notifier, - private blocklistService: BlocklistService, - private i18n: I18n - ) { - super() - } - - ngOnInit () { - this.initialize() - } +export class MyAccountServerBlocklistComponent extends GenericServerBlocklistComponent { + mode = BlocklistComponentType.Account getIdentifier () { return 'MyAccountServerBlocklistComponent' } - - unblockServer (serverBlock: ServerBlock) { - const host = serverBlock.blockedServer.host - - this.blocklistService.unblockServerByUser(host) - .subscribe( - () => { - this.notifier.success(this.i18n('Instance {{host}} unmuted.', { host })) - - this.loadData() - } - ) - } - - protected loadData () { - return this.blocklistService.getUserServerBlocklist(this.pagination, this.sort) - .subscribe( - resultList => { - this.blockedServers = resultList.data - this.totalRecords = resultList.total - }, - - err => this.notifier.error(err.message) - ) - } } 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 = [ component: MyAccountServerBlocklistComponent, data: { meta: { - title: 'Muted instances' + title: 'Muted servers' } } }, 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 { iconName: 'user' }, { - label: this.i18n('Muted instances'), + label: this.i18n('Muted servers'), routerLink: '/my-account/blocklist/servers', iconName: 'server' }, 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 @@ + + +
+
+ + + Clear filters +
+
+
+ + + + Account + Muted at + + + + + + + + +
+ Avatar +
+ {{ accountBlock.blockedAccount.displayName }} + {{ accountBlock.blockedAccount.nameWithHost }} +
+
+
+ + + {{ accountBlock.createdAt | date: 'short' }} + + + + +
+ + + + +
+ No account found matching current filters. + No account found. +
+ + +
+
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 @@ +@import '_variables'; +@import '_mixins'; + +.caption { + justify-content: flex-end; + + input { + @include peertube-input-text(250px); + flex-grow: 1; + } +} + +.unblock-button { + @include peertube-button; + @include grey-button; +} \ 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 @@ +import { OnInit } from '@angular/core' +import { Notifier } from '@app/core' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { RestPagination, RestTable } from '@app/shared/rest' +import { SortMeta } from 'primeng/api' +import { AccountBlock } from './account-block.model' +import { BlocklistService, BlocklistComponentType } from './blocklist.service' +import { Actor } from '@app/shared/actor/actor.model' + +export class GenericAccountBlocklistComponent extends RestTable implements OnInit { + // @ts-ignore: "Abstract methods can only appear within an abstract class" + abstract mode: BlocklistComponentType + + blockedAccounts: AccountBlock[] = [] + totalRecords = 0 + sort: SortMeta = { field: 'createdAt', order: -1 } + pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + + constructor ( + private notifier: Notifier, + private blocklistService: BlocklistService, + private i18n: I18n + ) { + super() + } + + // @ts-ignore: "Abstract methods can only appear within an abstract class" + abstract getIdentifier (): string + + ngOnInit () { + this.initialize() + } + + switchToDefaultAvatar ($event: Event) { + ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL() + } + + unblockAccount (accountBlock: AccountBlock) { + const blockedAccount = accountBlock.blockedAccount + const operation = this.mode === BlocklistComponentType.Account + ? this.blocklistService.unblockAccountByUser(blockedAccount) + : this.blocklistService.unblockAccountByInstance(blockedAccount) + + operation.subscribe( + () => { + this.notifier.success( + this.mode === BlocklistComponentType.Account + ? this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost }) + : this.i18n('Account {{nameWithHost}} unmuted by your instance.', { nameWithHost: blockedAccount.nameWithHost }) + ) + + this.loadData() + } + ) + } + + protected loadData () { + const operation = this.mode === BlocklistComponentType.Account + ? this.blocklistService.getUserAccountBlocklist({ + pagination: this.pagination, + sort: this.sort, + search: this.search + }) + : this.blocklistService.getInstanceAccountBlocklist({ + pagination: this.pagination, + sort: this.sort, + search: this.search + }) + + return operation.subscribe( + resultList => { + this.blockedAccounts = resultList.data + this.totalRecords = resultList.total + }, + + err => this.notifier.error(err.message) + ) + } +} 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 '../ import { Account } from '@app/shared/account/account.model' import { AccountBlock } from '@app/shared/blocklist/account-block.model' +export enum BlocklistComponentType { Account, Instance } + @Injectable() export class BlocklistService { static BASE_USER_BLOCKLIST_URL = environment.apiUrl + '/api/v1/users/me/blocklist' @@ -21,10 +23,14 @@ export class BlocklistService { /*********************** User -> Account blocklist ***********************/ - getUserAccountBlocklist (pagination: RestPagination, sort: SortMeta) { + getUserAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { + const { pagination, sort, search } = options + let params = new HttpParams() params = this.restService.addRestGetParams(params, pagination, sort) + if (search) params = params.append('search', search) + return this.authHttp.get>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', { params }) .pipe( map(res => this.restExtractor.convertResultListDateToHuman(res)), @@ -49,10 +55,14 @@ export class BlocklistService { /*********************** User -> Server blocklist ***********************/ - getUserServerBlocklist (pagination: RestPagination, sort: SortMeta) { + getUserServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { + const { pagination, sort, search } = options + let params = new HttpParams() params = this.restService.addRestGetParams(params, pagination, sort) + if (search) params = params.append('search', search) + return this.authHttp.get>(BlocklistService.BASE_USER_BLOCKLIST_URL + '/servers', { params }) .pipe( map(res => this.restExtractor.convertResultListDateToHuman(res)), @@ -76,7 +86,7 @@ export class BlocklistService { /*********************** Instance -> Account blocklist ***********************/ - getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) { + getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { const { pagination, sort, search } = options let params = new HttpParams() @@ -108,7 +118,7 @@ export class BlocklistService { /*********************** Instance -> Server blocklist ***********************/ - getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) { + getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { const { pagination, sort, search } = options 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 @@ export * from './blocklist.service' export * from './account-block.model' +export * from './server-blocklist.component' +export * 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 similarity index 98% rename from client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.html rename to 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 @@ -
+
No server found matching current filters. No server found.
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 similarity index 75% rename from client/src/app/+admin/moderation/instance-blocklist/instance-server-blocklist.component.scss rename to 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 { } } +.caption { + justify-content: flex-end; + + input { + @include peertube-input-text(250px); + flex-grow: 1; + } +} + .unblock-button { @include peertube-button; @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 @@ +import { OnInit, ViewChild } from '@angular/core' +import { Notifier } from '@app/core' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { RestPagination, RestTable } from '@app/shared/rest' +import { SortMeta } from 'primeng/api' +import { BlocklistService, BlocklistComponentType } from './blocklist.service' +import { ServerBlock } from '../../../../../shared/models/blocklist/server-block.model' +import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component' + +export class GenericServerBlocklistComponent extends RestTable implements OnInit { + @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent + + // @ts-ignore: "Abstract methods can only appear within an abstract class" + public abstract mode: BlocklistComponentType + + blockedServers: ServerBlock[] = [] + totalRecords = 0 + sort: SortMeta = { field: 'createdAt', order: -1 } + pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + + constructor ( + protected notifier: Notifier, + protected blocklistService: BlocklistService, + protected i18n: I18n + ) { + super() + } + + ngOnInit () { + this.initialize() + } + + // @ts-ignore: "Abstract methods can only appear within an abstract class" + public abstract getIdentifier (): string + + unblockServer (serverBlock: ServerBlock) { + const operation = (host: string) => this.mode === BlocklistComponentType.Account + ? this.blocklistService.unblockServerByUser(host) + : this.blocklistService.unblockServerByInstance(host) + const host = serverBlock.blockedServer.host + + operation(host).subscribe( + () => { + this.notifier.success( + this.mode === BlocklistComponentType.Account + ? this.i18n('Instance {{host}} unmuted.', { host }) + : this.i18n('Instance {{host}} unmuted by your instance.', { host }) + ) + + this.loadData() + } + ) + } + + addServersToBlock () { + this.batchDomainsModal.openModal() + } + + onDomainsToBlock (domains: string[]) { + const operation = (domain: string) => this.mode === BlocklistComponentType.Account + ? this.blocklistService.blockServerByUser(domain) + : this.blocklistService.blockServerByInstance(domain) + + domains.forEach(domain => { + operation(domain).subscribe( + () => { + this.notifier.success( + this.mode === BlocklistComponentType.Account + ? this.i18n('Instance {{domain}} muted.', { domain }) + : this.i18n('Instance {{domain}} muted by your instance.', { domain }) + ) + + this.loadData() + } + ) + }) + } + + protected loadData () { + const operation = this.mode === BlocklistComponentType.Account + ? this.blocklistService.getUserServerBlocklist({ + pagination: this.pagination, + sort: this.sort, + search: this.search + }) + : this.blocklistService.getInstanceServerBlocklist({ + pagination: this.pagination, + sort: this.sort, + search: this.search + }) + + return operation.subscribe( + resultList => { + this.blockedServers = resultList.data + this.totalRecords = resultList.total + }, + + err => this.notifier.error(err.message) + ) + } +} 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' import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { RouterModule } from '@angular/router' import { BatchDomainsValidatorsService } from '@app/+admin/config/shared/batch-domains-validators.service' +import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-domains-modal.component' import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface' import { MyAccountVideoSettingsComponent } from '@app/+my-account/my-account-settings/my-account-video-settings' import { ActorAvatarInfoComponent } from '@app/+my-account/shared/actor-avatar-info.component' @@ -192,7 +193,8 @@ import { VideoService } from './video/video.service' MyAccountVideoSettingsComponent, MyAccountInterfaceSettingsComponent, - ActorAvatarInfoComponent + ActorAvatarInfoComponent, + BatchDomainsModalComponent ], exports: [ @@ -274,7 +276,8 @@ import { VideoService } from './video/video.service' MyAccountVideoSettingsComponent, MyAccountInterfaceSettingsComponent, - ActorAvatarInfoComponent + ActorAvatarInfoComponent, + BatchDomainsModalComponent ], 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 { .no-results { height: 40vh; + max-height: 500px; + display: flex; align-items: center; 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 @@ } } -@mixin empty-state { - min-height: 40vh; - max-height: 500px; - - display: flex; - justify-content: center; - align-items: center; -} - @mixin admin-sub-header-responsive ($horizontal-margins) { flex-direction: column;