aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+accounts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-08-25 11:42:30 +0200
committerChocobozzz <me@florianbigard.com>2021-08-25 11:42:30 +0200
commitfdec51e3846d50e3375612a6820ed3ab0b5fcd25 (patch)
tree17283e85a6794c9e8fe3f5d4478a406d8d188425 /client/src/app/+accounts
parent59c8902a57991be29f0aacac1642389fb770c6ed (diff)
parentdd24f1bb0a4b252e5342b251ba36853364da7b8e (diff)
downloadPeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.tar.gz
PeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.tar.zst
PeerTube-fdec51e3846d50e3375612a6820ed3ab0b5fcd25.zip
Merge branch 'feature/video-filters' into develop
Diffstat (limited to 'client/src/app/+accounts')
-rw-r--r--client/src/app/+accounts/account-search/account-search.component.ts110
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.html2
-rw-r--r--client/src/app/+accounts/account-videos/account-videos.component.html20
-rw-r--r--client/src/app/+accounts/account-videos/account-videos.component.ts93
-rw-r--r--client/src/app/+accounts/accounts-routing.module.ts10
-rw-r--r--client/src/app/+accounts/accounts.component.html4
-rw-r--r--client/src/app/+accounts/accounts.component.scss5
-rw-r--r--client/src/app/+accounts/accounts.component.ts22
-rw-r--r--client/src/app/+accounts/accounts.module.ts6
9 files changed, 74 insertions, 198 deletions
diff --git a/client/src/app/+accounts/account-search/account-search.component.ts b/client/src/app/+accounts/account-search/account-search.component.ts
deleted file mode 100644
index f54ab846a..000000000
--- a/client/src/app/+accounts/account-search/account-search.component.ts
+++ /dev/null
@@ -1,110 +0,0 @@
1import { forkJoin, Subscription } from 'rxjs'
2import { first, tap } from 'rxjs/operators'
3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router'
5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
6import { immutableAssign } from '@app/helpers'
7import { Account, AccountService, VideoService } from '@app/shared/shared-main'
8import { AbstractVideoList } from '@app/shared/shared-video-miniature'
9import { VideoFilter } from '@shared/models'
10
11@Component({
12 selector: 'my-account-search',
13 templateUrl: '../../shared/shared-video-miniature/abstract-video-list.html',
14 styleUrls: [ '../../shared/shared-video-miniature/abstract-video-list.scss' ]
15})
16export class AccountSearchComponent extends AbstractVideoList implements OnInit, OnDestroy {
17 titlePage: string
18 loadOnInit = false
19 loadUserVideoPreferences = true
20
21 search = ''
22 filter: VideoFilter = null
23
24 private account: Account
25 private accountSub: Subscription
26
27 constructor (
28 protected router: Router,
29 protected serverService: ServerService,
30 protected route: ActivatedRoute,
31 protected authService: AuthService,
32 protected userService: UserService,
33 protected notifier: Notifier,
34 protected confirmService: ConfirmService,
35 protected screenService: ScreenService,
36 protected storageService: LocalStorageService,
37 protected cfr: ComponentFactoryResolver,
38 private accountService: AccountService,
39 private videoService: VideoService
40 ) {
41 super()
42 }
43
44 ngOnInit () {
45 super.ngOnInit()
46
47 this.enableAllFilterIfPossible()
48
49 // Parent get the account for us
50 this.accountSub = forkJoin([
51 this.accountService.accountLoaded.pipe(first()),
52 this.onUserLoadedSubject.pipe(first())
53 ]).subscribe(([ account ]) => {
54 this.account = account
55
56 this.reloadVideos()
57 })
58 }
59
60 ngOnDestroy () {
61 if (this.accountSub) this.accountSub.unsubscribe()
62
63 super.ngOnDestroy()
64 }
65
66 updateSearch (value: string) {
67 this.search = value
68
69 if (!this.search) {
70 this.router.navigate([ '../videos' ], { relativeTo: this.route })
71 return
72 }
73
74 this.videos = []
75 this.reloadVideos()
76 }
77
78 getVideosObservable (page: number) {
79 const newPagination = immutableAssign(this.pagination, { currentPage: page })
80 const options = {
81 account: this.account,
82 videoPagination: newPagination,
83 sort: this.sort,
84 nsfwPolicy: this.nsfwPolicy,
85 videoFilter: this.filter,
86 search: this.search
87 }
88
89 return this.videoService
90 .getAccountVideos(options)
91 .pipe(
92 tap(({ total }) => {
93 this.titlePage = this.search
94 ? $localize`Published ${total} videos matching "${this.search}"`
95 : $localize`Published ${total} videos`
96 })
97 )
98 }
99
100 toggleModerationDisplay () {
101 this.filter = this.buildLocalFilter(this.filter, null)
102
103 this.reloadVideos()
104 }
105
106 generateSyndicationList () {
107 /* method disabled */
108 throw new Error('Method not implemented.')
109 }
110}
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
index 922608127..105bc12c3 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
@@ -4,7 +4,7 @@
4 4
5 <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div> 5 <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div>
6 6
7 <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onChannelDataSubject.asObservable()"> 7 <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [dataObservable]="onChannelDataSubject.asObservable()">
8 <div class="channel" *ngFor="let videoChannel of videoChannels"> 8 <div class="channel" *ngFor="let videoChannel of videoChannels">
9 9
10 <div class="channel-avatar-row"> 10 <div class="channel-avatar-row">
diff --git a/client/src/app/+accounts/account-videos/account-videos.component.html b/client/src/app/+accounts/account-videos/account-videos.component.html
new file mode 100644
index 000000000..5b4b0937f
--- /dev/null
+++ b/client/src/app/+accounts/account-videos/account-videos.component.html
@@ -0,0 +1,20 @@
1<my-videos-list
2 *ngIf="account"
3
4 [title]="title"
5 [displayTitle]="false"
6
7 [getVideosObservableFunction]="getVideosObservableFunction"
8 [getSyndicationItemsFunction]="getSyndicationItemsFunction"
9
10 [defaultSort]="defaultSort"
11
12 [displayFilters]="true"
13 [displayModerationBlock]="true"
14 [displayAsRow]="displayAsRow()"
15
16 [loadUserVideoPreferences]="true"
17
18 [disabled]="disabled"
19>
20</my-videos-list>
diff --git a/client/src/app/+accounts/account-videos/account-videos.component.ts b/client/src/app/+accounts/account-videos/account-videos.component.ts
index 4ab6d2147..13d1f857d 100644
--- a/client/src/app/+accounts/account-videos/account-videos.component.ts
+++ b/client/src/app/+accounts/account-videos/account-videos.component.ts
@@ -1,96 +1,69 @@
1import { forkJoin, Subscription } from 'rxjs' 1import { Subscription } from 'rxjs'
2import { first } from 'rxjs/operators' 2import { first } from 'rxjs/operators'
3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core' 3import { Component, OnDestroy, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ComponentPaginationLight, DisableForReuseHook, ScreenService } from '@app/core'
5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
6import { immutableAssign } from '@app/helpers'
7import { Account, AccountService, VideoService } from '@app/shared/shared-main' 5import { Account, AccountService, VideoService } from '@app/shared/shared-main'
8import { AbstractVideoList } from '@app/shared/shared-video-miniature' 6import { VideoFilters } from '@app/shared/shared-video-miniature'
9import { VideoFilter } from '@shared/models' 7import { VideoSortField } from '@shared/models'
10 8
11@Component({ 9@Component({
12 selector: 'my-account-videos', 10 selector: 'my-account-videos',
13 templateUrl: '../../shared/shared-video-miniature/abstract-video-list.html', 11 templateUrl: './account-videos.component.html'
14 styleUrls: [
15 '../../shared/shared-video-miniature/abstract-video-list.scss'
16 ]
17}) 12})
18export class AccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy { 13export class AccountVideosComponent implements OnInit, OnDestroy, DisableForReuseHook {
19 // No value because we don't want a page title 14 getVideosObservableFunction = this.getVideosObservable.bind(this)
20 titlePage: string 15 getSyndicationItemsFunction = this.getSyndicationItems.bind(this)
21 loadOnInit = false
22 loadUserVideoPreferences = true
23 16
24 filter: VideoFilter = null 17 title = $localize`Videos`
18 defaultSort = '-publishedAt' as VideoSortField
19
20 account: Account
21 disabled = false
25 22
26 private account: Account
27 private accountSub: Subscription 23 private accountSub: Subscription
28 24
29 constructor ( 25 constructor (
30 protected router: Router, 26 private screenService: ScreenService,
31 protected serverService: ServerService,
32 protected route: ActivatedRoute,
33 protected authService: AuthService,
34 protected userService: UserService,
35 protected notifier: Notifier,
36 protected confirmService: ConfirmService,
37 protected screenService: ScreenService,
38 protected storageService: LocalStorageService,
39 private accountService: AccountService, 27 private accountService: AccountService,
40 private videoService: VideoService, 28 private videoService: VideoService
41 protected cfr: ComponentFactoryResolver
42 ) { 29 ) {
43 super()
44 } 30 }
45 31
46 ngOnInit () { 32 ngOnInit () {
47 super.ngOnInit()
48
49 this.enableAllFilterIfPossible()
50
51 // Parent get the account for us 33 // Parent get the account for us
52 this.accountSub = forkJoin([ 34 this.accountService.accountLoaded.pipe(first())
53 this.accountService.accountLoaded.pipe(first()), 35 .subscribe(account => this.account = account)
54 this.onUserLoadedSubject.pipe(first())
55 ]).subscribe(([ account ]) => {
56 this.account = account
57
58 this.reloadVideos()
59 this.generateSyndicationList()
60 })
61 } 36 }
62 37
63 ngOnDestroy () { 38 ngOnDestroy () {
64 if (this.accountSub) this.accountSub.unsubscribe() 39 if (this.accountSub) this.accountSub.unsubscribe()
65
66 super.ngOnDestroy()
67 } 40 }
68 41
69 getVideosObservable (page: number) { 42 getVideosObservable (pagination: ComponentPaginationLight, filters: VideoFilters) {
70 const newPagination = immutableAssign(this.pagination, { currentPage: page })
71 const options = { 43 const options = {
44 ...filters.toVideosAPIObject(),
45
46 videoPagination: pagination,
72 account: this.account, 47 account: this.account,
73 videoPagination: newPagination, 48 skipCount: true
74 sort: this.sort,
75 nsfwPolicy: this.nsfwPolicy,
76 videoFilter: this.filter
77 } 49 }
78 50
79 return this.videoService 51 return this.videoService.getAccountVideos(options)
80 .getAccountVideos(options)
81 } 52 }
82 53
83 toggleModerationDisplay () { 54 getSyndicationItems () {
84 this.filter = this.buildLocalFilter(this.filter, null) 55 return this.videoService.getAccountFeedUrls(this.account.id)
56 }
85 57
86 this.reloadVideos() 58 displayAsRow () {
59 return this.screenService.isInMobileView()
87 } 60 }
88 61
89 generateSyndicationList () { 62 disableForReuse () {
90 this.syndicationItems = this.videoService.getAccountFeedUrls(this.account.id) 63 this.disabled = true
91 } 64 }
92 65
93 displayAsRow () { 66 enabledForReuse () {
94 return this.screenService.isInMobileView() 67 this.disabled = false
95 } 68 }
96} 69}
diff --git a/client/src/app/+accounts/accounts-routing.module.ts b/client/src/app/+accounts/accounts-routing.module.ts
index 2f3792a8d..d80df2293 100644
--- a/client/src/app/+accounts/accounts-routing.module.ts
+++ b/client/src/app/+accounts/accounts-routing.module.ts
@@ -1,6 +1,5 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { RouterModule, Routes } from '@angular/router' 2import { RouterModule, Routes } from '@angular/router'
3import { AccountSearchComponent } from './account-search/account-search.component'
4import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component' 3import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
5import { AccountVideosComponent } from './account-videos/account-videos.component' 4import { AccountVideosComponent } from './account-videos/account-videos.component'
6import { AccountsComponent } from './accounts.component' 5import { AccountsComponent } from './accounts.component'
@@ -41,14 +40,11 @@ const accountsRoutes: Routes = [
41 } 40 }
42 } 41 }
43 }, 42 },
43
44 // Old URL redirection
44 { 45 {
45 path: 'search', 46 path: 'search',
46 component: AccountSearchComponent, 47 redirectTo: 'videos'
47 data: {
48 meta: {
49 title: $localize`Search videos within account`
50 }
51 }
52 } 48 }
53 ] 49 ]
54 } 50 }
diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html
index 0906992fe..245edfd58 100644
--- a/client/src/app/+accounts/accounts.component.html
+++ b/client/src/app/+accounts/accounts.component.html
@@ -66,7 +66,7 @@
66 </div> 66 </div>
67 </div> 67 </div>
68 68
69 <div class="links"> 69 <div class="links" [ngClass]="{ 'on-channel-page': isOnChannelPage() }">
70 <ng-template #linkTemplate let-item="item"> 70 <ng-template #linkTemplate let-item="item">
71 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a> 71 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
72 </ng-template> 72 </ng-template>
@@ -81,7 +81,7 @@
81 ></my-simple-search-input> 81 ></my-simple-search-input>
82 </div> 82 </div>
83 83
84 <router-outlet (activate)="onOutletLoaded($event)"></router-outlet> 84 <router-outlet></router-outlet>
85</div> 85</div>
86 86
87<ng-container *ngIf="prependModerationActions"> 87<ng-container *ngIf="prependModerationActions">
diff --git a/client/src/app/+accounts/accounts.component.scss b/client/src/app/+accounts/accounts.component.scss
index 4c1f94024..c4e2159d1 100644
--- a/client/src/app/+accounts/accounts.component.scss
+++ b/client/src/app/+accounts/accounts.component.scss
@@ -20,7 +20,10 @@
20 display: flex; 20 display: flex;
21 justify-content: space-between; 21 justify-content: space-between;
22 align-items: center; 22 align-items: center;
23 max-width: $max-channels-width; 23
24 &.on-channel-page {
25 max-width: $max-channels-width;
26 }
24 27
25 simple-search-input { 28 simple-search-input {
26 @include margin-left(auto); 29 @include margin-left(auto);
diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts
index 733cff8d5..e90816c5a 100644
--- a/client/src/app/+accounts/accounts.component.ts
+++ b/client/src/app/+accounts/accounts.component.ts
@@ -1,7 +1,7 @@
1import { Subscription } from 'rxjs' 1import { Subscription } from 'rxjs'
2import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators' 2import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators'
3import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' 3import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
4import { ActivatedRoute } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { AuthService, MarkdownService, Notifier, RedirectService, RestExtractor, ScreenService, UserService } from '@app/core' 5import { AuthService, MarkdownService, Notifier, RedirectService, RestExtractor, ScreenService, UserService } from '@app/core'
6import { 6import {
7 Account, 7 Account,
@@ -14,7 +14,6 @@ import {
14} from '@app/shared/shared-main' 14} from '@app/shared/shared-main'
15import { AccountReportComponent } from '@app/shared/shared-moderation' 15import { AccountReportComponent } from '@app/shared/shared-moderation'
16import { HttpStatusCode, User, UserRight } from '@shared/models' 16import { HttpStatusCode, User, UserRight } from '@shared/models'
17import { AccountSearchComponent } from './account-search/account-search.component'
18 17
19@Component({ 18@Component({
20 templateUrl: './accounts.component.html', 19 templateUrl: './accounts.component.html',
@@ -23,8 +22,6 @@ import { AccountSearchComponent } from './account-search/account-search.componen
23export class AccountsComponent implements OnInit, OnDestroy { 22export class AccountsComponent implements OnInit, OnDestroy {
24 @ViewChild('accountReportModal') accountReportModal: AccountReportComponent 23 @ViewChild('accountReportModal') accountReportModal: AccountReportComponent
25 24
26 accountSearch: AccountSearchComponent
27
28 account: Account 25 account: Account
29 accountUser: User 26 accountUser: User
30 27
@@ -45,6 +42,7 @@ export class AccountsComponent implements OnInit, OnDestroy {
45 42
46 constructor ( 43 constructor (
47 private route: ActivatedRoute, 44 private route: ActivatedRoute,
45 private router: Router,
48 private userService: UserService, 46 private userService: UserService,
49 private accountService: AccountService, 47 private accountService: AccountService,
50 private videoChannelService: VideoChannelService, 48 private videoChannelService: VideoChannelService,
@@ -128,16 +126,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
128 return $localize`${count} subscribers` 126 return $localize`${count} subscribers`
129 } 127 }
130 128
131 onOutletLoaded (component: Component) {
132 if (component instanceof AccountSearchComponent) {
133 this.accountSearch = component
134 } else {
135 this.accountSearch = undefined
136 }
137 }
138
139 searchChanged (search: string) { 129 searchChanged (search: string) {
140 if (this.accountSearch) this.accountSearch.updateSearch(search) 130 const queryParams = { search }
131
132 this.router.navigate([ './videos' ], { queryParams, relativeTo: this.route, queryParamsHandling: 'merge' })
141 } 133 }
142 134
143 onSearchInputDisplayChanged (displayed: boolean) { 135 onSearchInputDisplayChanged (displayed: boolean) {
@@ -152,6 +144,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
152 return !this.accountDescriptionExpanded && this.accountDescriptionHTML.length > 100 144 return !this.accountDescriptionExpanded && this.accountDescriptionHTML.length > 100
153 } 145 }
154 146
147 isOnChannelPage () {
148 return this.route.children[0].snapshot.url[0].path === 'video-channels'
149 }
150
155 private async onAccount (account: Account) { 151 private async onAccount (account: Account) {
156 this.accountFollowerTitle = $localize`${account.followersCount} direct account followers` 152 this.accountFollowerTitle = $localize`${account.followersCount} direct account followers`
157 153
diff --git a/client/src/app/+accounts/accounts.module.ts b/client/src/app/+accounts/accounts.module.ts
index 1bafc5141..aedc69b16 100644
--- a/client/src/app/+accounts/accounts.module.ts
+++ b/client/src/app/+accounts/accounts.module.ts
@@ -5,12 +5,11 @@ import { SharedMainModule } from '@app/shared/shared-main'
5import { SharedModerationModule } from '@app/shared/shared-moderation' 5import { SharedModerationModule } from '@app/shared/shared-moderation'
6import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription' 6import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription'
7import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature' 7import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
8import { AccountSearchComponent } from './account-search/account-search.component' 8import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
9import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component' 9import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
10import { AccountVideosComponent } from './account-videos/account-videos.component' 10import { AccountVideosComponent } from './account-videos/account-videos.component'
11import { AccountsRoutingModule } from './accounts-routing.module' 11import { AccountsRoutingModule } from './accounts-routing.module'
12import { AccountsComponent } from './accounts.component' 12import { AccountsComponent } from './accounts.component'
13import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
14 13
15@NgModule({ 14@NgModule({
16 imports: [ 15 imports: [
@@ -28,8 +27,7 @@ import { SharedActorImageModule } from '../shared/shared-actor-image/shared-acto
28 declarations: [ 27 declarations: [
29 AccountsComponent, 28 AccountsComponent,
30 AccountVideosComponent, 29 AccountVideosComponent,
31 AccountVideoChannelsComponent, 30 AccountVideoChannelsComponent
32 AccountSearchComponent
33 ], 31 ],
34 32
35 exports: [ 33 exports: [