From a6dbbf03865a955caaedc3b12f3de3e386fe850f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 6 Jun 2019 11:39:22 +0200 Subject: Add list of instance follows in about page --- .../about-follows/about-follows.component.html | 22 +++++ .../about-follows/about-follows.component.scss | 14 +++ .../about-follows/about-follows.component.ts | 103 +++++++++++++++++++++ client/src/app/+about/about-routing.module.ts | 10 ++ client/src/app/+about/about.component.html | 4 +- client/src/app/+about/about.module.ts | 2 + client/src/app/+admin/admin.module.ts | 3 +- .../followers-list/followers-list.component.ts | 2 +- .../following-add/following-add.component.ts | 2 +- .../following-list/following-list.component.ts | 2 +- client/src/app/+admin/follows/index.ts | 1 - .../app/+admin/follows/shared/follow.service.ts | 96 ------------------- client/src/app/+admin/follows/shared/index.ts | 1 - client/src/app/shared/instance/follow.service.ts | 96 +++++++++++++++++++ client/src/app/shared/shared.module.ts | 3 + .../src/app/shared/video/abstract-video-list.html | 1 - 16 files changed, 257 insertions(+), 105 deletions(-) create mode 100644 client/src/app/+about/about-follows/about-follows.component.html create mode 100644 client/src/app/+about/about-follows/about-follows.component.scss create mode 100644 client/src/app/+about/about-follows/about-follows.component.ts delete mode 100644 client/src/app/+admin/follows/shared/follow.service.ts delete mode 100644 client/src/app/+admin/follows/shared/index.ts create mode 100644 client/src/app/shared/instance/follow.service.ts diff --git a/client/src/app/+about/about-follows/about-follows.component.html b/client/src/app/+about/about-follows/about-follows.component.html new file mode 100644 index 000000000..18689bbf7 --- /dev/null +++ b/client/src/app/+about/about-follows/about-follows.component.html @@ -0,0 +1,22 @@ +
+
+
Followers
+ +
This instance does not have followers.
+ + + {{ follower }} + +
+ +
+
Followings
+ +
This instance does not have followings.
+ + + {{ following }} + +
+ +
diff --git a/client/src/app/+about/about-follows/about-follows.component.scss b/client/src/app/+about/about-follows/about-follows.component.scss new file mode 100644 index 000000000..e0d597a96 --- /dev/null +++ b/client/src/app/+about/about-follows/about-follows.component.scss @@ -0,0 +1,14 @@ +@import '_variables'; +@import '_mixins'; + +.subtitle { + font-size: 18px; + font-weight: $font-semibold; + margin-bottom: 20px; +} + +a { + display: block; + width: fit-content; + margin-top: 3px; +} diff --git a/client/src/app/+about/about-follows/about-follows.component.ts b/client/src/app/+about/about-follows/about-follows.component.ts new file mode 100644 index 000000000..f0e1375d6 --- /dev/null +++ b/client/src/app/+about/about-follows/about-follows.component.ts @@ -0,0 +1,103 @@ +import { Component, OnInit } from '@angular/core' +import { FollowService } from '@app/shared/instance/follow.service' +import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model' +import { Notifier } from '@app/core' +import { RestService } from '@app/shared' +import { SortMeta } from 'primeng/api' + +@Component({ + selector: 'my-about-follows', + templateUrl: './about-follows.component.html', + styleUrls: [ './about-follows.component.scss' ] +}) + +export class AboutFollowsComponent implements OnInit { + followers: string[] = [] + followings: string[] = [] + + followersPagination: ComponentPagination = { + currentPage: 1, + itemsPerPage: 40, + totalItems: null + } + + followingsPagination: ComponentPagination = { + currentPage: 1, + itemsPerPage: 40, + totalItems: null + } + + sort: SortMeta = { + field: 'createdAt', + order: -1 + } + + constructor ( + private restService: RestService, + private notifier: Notifier, + private followService: FollowService + ) { } + + ngOnInit () { + this.loadMoreFollowers() + + this.loadMoreFollowings() + } + + onNearOfBottom () { + this.onNearOfFollowersBottom() + + this.onNearOfFollowingsBottom() + } + + onNearOfFollowersBottom () { + if (!hasMoreItems(this.followersPagination)) return + + this.followersPagination.currentPage += 1 + this.loadMoreFollowers() + } + + onNearOfFollowingsBottom () { + if (!hasMoreItems(this.followingsPagination)) return + + this.followingsPagination.currentPage += 1 + this.loadMoreFollowings() + } + + buildLink (host: string) { + return window.location.protocol + '//' + host + } + + private loadMoreFollowers () { + const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination) + + this.followService.getFollowers(pagination, this.sort) + .subscribe( + resultList => { + const newFollowers = resultList.data.map(r => r.follower.host) + this.followers = this.followers.concat(newFollowers) + + this.followersPagination.totalItems = resultList.total + }, + + err => this.notifier.error(err.message) + ) + } + + private loadMoreFollowings () { + const pagination = this.restService.componentPaginationToRestPagination(this.followingsPagination) + + this.followService.getFollowing(pagination, this.sort) + .subscribe( + resultList => { + const newFollowings = resultList.data.map(r => r.following.host) + this.followings = this.followings.concat(newFollowings) + + this.followingsPagination.totalItems = resultList.total + }, + + err => this.notifier.error(err.message) + ) + } + +} diff --git a/client/src/app/+about/about-routing.module.ts b/client/src/app/+about/about-routing.module.ts index c83c62c7f..33e5070cb 100644 --- a/client/src/app/+about/about-routing.module.ts +++ b/client/src/app/+about/about-routing.module.ts @@ -4,6 +4,7 @@ import { MetaGuard } from '@ngx-meta/core' import { AboutComponent } from './about.component' import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component' import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component' +import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component' const aboutRoutes: Routes = [ { @@ -33,6 +34,15 @@ const aboutRoutes: Routes = [ title: 'About PeerTube' } } + }, + { + path: 'follows', + component: AboutFollowsComponent, + data: { + meta: { + title: 'About follows' + } + } } ] } diff --git a/client/src/app/+about/about.component.html b/client/src/app/+about/about.component.html index 8c50835c1..0c4a5156d 100644 --- a/client/src/app/+about/about.component.html +++ b/client/src/app/+about/about.component.html @@ -5,10 +5,12 @@ Instance PeerTube + + Follows
- \ No newline at end of file + diff --git a/client/src/app/+about/about.module.ts b/client/src/app/+about/about.module.ts index 9c6b29740..49a7a52f8 100644 --- a/client/src/app/+about/about.module.ts +++ b/client/src/app/+about/about.module.ts @@ -6,6 +6,7 @@ import { SharedModule } from '../shared' import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component' import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component' import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component' +import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component' @NgModule({ imports: [ @@ -17,6 +18,7 @@ import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-a AboutComponent, AboutInstanceComponent, AboutPeertubeComponent, + AboutFollowsComponent, ContactAdminModalComponent ], diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index 71a4dfc4a..9ab883f60 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts @@ -5,7 +5,7 @@ import { TableModule } from 'primeng/table' import { SharedModule } from '../shared' import { AdminRoutingModule } from './admin-routing.module' import { AdminComponent } from './admin.component' -import { FollowersListComponent, FollowingAddComponent, FollowsComponent, FollowService } from './follows' +import { FollowersListComponent, FollowingAddComponent, FollowsComponent } from './follows' import { FollowingListComponent } from './follows/following-list/following-list.component' import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersComponent, UserUpdateComponent } from './users' import { @@ -66,7 +66,6 @@ import { DebugComponent, DebugService } from '@app/+admin/system/debug' ], providers: [ - FollowService, RedundancyService, JobService, LogsService, diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.ts b/client/src/app/+admin/follows/followers-list/followers-list.component.ts index b78cdf656..e25d9ab66 100644 --- a/client/src/app/+admin/follows/followers-list/followers-list.component.ts +++ b/client/src/app/+admin/follows/followers-list/followers-list.component.ts @@ -3,7 +3,7 @@ import { ConfirmService, Notifier } from '@app/core' import { SortMeta } from 'primeng/primeng' import { ActorFollow } from '../../../../../../shared/models/actors/follow.model' import { RestPagination, RestTable } from '../../../shared' -import { FollowService } from '../shared' +import { FollowService } from '@app/shared/instance/follow.service' import { I18n } from '@ngx-translate/i18n-polyfill' @Component({ diff --git a/client/src/app/+admin/follows/following-add/following-add.component.ts b/client/src/app/+admin/follows/following-add/following-add.component.ts index 2bb249746..308bbb0c5 100644 --- a/client/src/app/+admin/follows/following-add/following-add.component.ts +++ b/client/src/app/+admin/follows/following-add/following-add.component.ts @@ -3,7 +3,7 @@ import { Router } from '@angular/router' import { Notifier } from '@app/core' import { ConfirmService } from '../../../core' import { validateHost } from '../../../shared' -import { FollowService } from '../shared' +import { FollowService } from '@app/shared/instance/follow.service' import { I18n } from '@ngx-translate/i18n-polyfill' @Component({ diff --git a/client/src/app/+admin/follows/following-list/following-list.component.ts b/client/src/app/+admin/follows/following-list/following-list.component.ts index 4517a721e..ded616624 100644 --- a/client/src/app/+admin/follows/following-list/following-list.component.ts +++ b/client/src/app/+admin/follows/following-list/following-list.component.ts @@ -4,7 +4,7 @@ import { SortMeta } from 'primeng/primeng' import { ActorFollow } from '../../../../../../shared/models/actors/follow.model' import { ConfirmService } from '../../../core/confirm/confirm.service' import { RestPagination, RestTable } from '../../../shared' -import { FollowService } from '../shared' +import { FollowService } from '@app/shared/instance/follow.service' import { I18n } from '@ngx-translate/i18n-polyfill' @Component({ diff --git a/client/src/app/+admin/follows/index.ts b/client/src/app/+admin/follows/index.ts index 7849a06e7..e94f33710 100644 --- a/client/src/app/+admin/follows/index.ts +++ b/client/src/app/+admin/follows/index.ts @@ -1,6 +1,5 @@ export * from './following-add' export * from './followers-list' export * from './following-list' -export * from './shared' export * from './follows.component' export * from './follows.routes' diff --git a/client/src/app/+admin/follows/shared/follow.service.ts b/client/src/app/+admin/follows/shared/follow.service.ts deleted file mode 100644 index c2b8ef006..000000000 --- a/client/src/app/+admin/follows/shared/follow.service.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { catchError, map } from 'rxjs/operators' -import { HttpClient, HttpParams } from '@angular/common/http' -import { Injectable } from '@angular/core' -import { SortMeta } from 'primeng/primeng' -import { Observable } from 'rxjs' -import { ActorFollow, ResultList } from '../../../../../../shared' -import { environment } from '../../../../environments/environment' -import { RestExtractor, RestPagination, RestService } from '../../../shared' - -@Injectable() -export class FollowService { - private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/server' - - constructor ( - private authHttp: HttpClient, - private restService: RestService, - private restExtractor: RestExtractor - ) { - } - - getFollowing (pagination: RestPagination, sort: SortMeta, search?: string): Observable> { - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, sort) - - if (search) params = params.append('search', search) - - return this.authHttp.get>(FollowService.BASE_APPLICATION_URL + '/following', { params }) - .pipe( - map(res => this.restExtractor.convertResultListDateToHuman(res)), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - getFollowers (pagination: RestPagination, sort: SortMeta, search?: string): Observable> { - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, sort) - - if (search) params = params.append('search', search) - - return this.authHttp.get>(FollowService.BASE_APPLICATION_URL + '/followers', { params }) - .pipe( - map(res => this.restExtractor.convertResultListDateToHuman(res)), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - follow (notEmptyHosts: string[]) { - const body = { - hosts: notEmptyHosts - } - - return this.authHttp.post(FollowService.BASE_APPLICATION_URL + '/following', body) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - unfollow (follow: ActorFollow) { - return this.authHttp.delete(FollowService.BASE_APPLICATION_URL + '/following/' + follow.following.host) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - acceptFollower (follow: ActorFollow) { - const handle = follow.follower.name + '@' + follow.follower.host - - return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/accept`, {}) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - rejectFollower (follow: ActorFollow) { - const handle = follow.follower.name + '@' + follow.follower.host - - return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/reject`, {}) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } - - removeFollower (follow: ActorFollow) { - const handle = follow.follower.name + '@' + follow.follower.host - - return this.authHttp.delete(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}`) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(res => this.restExtractor.handleError(res)) - ) - } -} diff --git a/client/src/app/+admin/follows/shared/index.ts b/client/src/app/+admin/follows/shared/index.ts deleted file mode 100644 index 78d456def..000000000 --- a/client/src/app/+admin/follows/shared/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './follow.service' diff --git a/client/src/app/shared/instance/follow.service.ts b/client/src/app/shared/instance/follow.service.ts new file mode 100644 index 000000000..5a44c64f1 --- /dev/null +++ b/client/src/app/shared/instance/follow.service.ts @@ -0,0 +1,96 @@ +import { catchError, map } from 'rxjs/operators' +import { HttpClient, HttpParams } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { SortMeta } from 'primeng/primeng' +import { Observable } from 'rxjs' +import { ActorFollow, ResultList } from '@shared/index' +import { environment } from '../../../environments/environment' +import { RestExtractor, RestPagination, RestService } from '../rest' + +@Injectable() +export class FollowService { + private static BASE_APPLICATION_URL = 'https://peertube2.cpy.re' + '/api/v1/server' + + constructor ( + private authHttp: HttpClient, + private restService: RestService, + private restExtractor: RestExtractor + ) { + } + + getFollowing (pagination: RestPagination, sort: SortMeta, search?: string): Observable> { + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination, sort) + + if (search) params = params.append('search', search) + + return this.authHttp.get>(FollowService.BASE_APPLICATION_URL + '/following', { params }) + .pipe( + map(res => this.restExtractor.convertResultListDateToHuman(res)), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + getFollowers (pagination: RestPagination, sort: SortMeta, search?: string): Observable> { + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination, sort) + + if (search) params = params.append('search', search) + + return this.authHttp.get>(FollowService.BASE_APPLICATION_URL + '/followers', { params }) + .pipe( + map(res => this.restExtractor.convertResultListDateToHuman(res)), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + follow (notEmptyHosts: string[]) { + const body = { + hosts: notEmptyHosts + } + + return this.authHttp.post(FollowService.BASE_APPLICATION_URL + '/following', body) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + unfollow (follow: ActorFollow) { + return this.authHttp.delete(FollowService.BASE_APPLICATION_URL + '/following/' + follow.following.host) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + acceptFollower (follow: ActorFollow) { + const handle = follow.follower.name + '@' + follow.follower.host + + return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/accept`, {}) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + rejectFollower (follow: ActorFollow) { + const handle = follow.follower.name + '@' + follow.follower.host + + return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/reject`, {}) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } + + removeFollower (follow: ActorFollow) { + const handle = follow.follower.name + '@' + follow.follower.host + + return this.authHttp.delete(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}`) + .pipe( + map(this.restExtractor.extractDataBool), + catchError(res => this.restExtractor.handleError(res)) + ) + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 39f1a69e2..1d49c7bc8 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -85,6 +85,7 @@ import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklis import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.component' import { VideoReportComponent } from '@app/shared/video/modals/video-report.component' import { ClipboardModule } from 'ngx-clipboard' +import { FollowService } from '@app/shared/instance/follow.service' @NgModule({ imports: [ @@ -271,6 +272,8 @@ import { ClipboardModule } from 'ngx-clipboard' UserNotificationService, + FollowService, + I18n ] }) diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html index 11cf1bd92..efd369bca 100644 --- a/client/src/app/shared/video/abstract-video-list.html +++ b/client/src/app/shared/video/abstract-video-list.html @@ -27,7 +27,6 @@ {{ getCurrentGroupedDateLabel(video) }} -