diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2021-01-13 09:16:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-13 09:16:15 +0100 |
commit | d8b34ee55b654912f86bb8b472d391ced8c28f64 (patch) | |
tree | efa2b8ac36c00fa6e9b5af3f13e54a47bc7a7701 /client | |
parent | 22078471fbe5a4dea6177bd1fa19da1cf887679e (diff) | |
download | PeerTube-d8b34ee55b654912f86bb8b472d391ced8c28f64.tar.gz PeerTube-d8b34ee55b654912f86bb8b472d391ced8c28f64.tar.zst PeerTube-d8b34ee55b654912f86bb8b472d391ced8c28f64.zip |
Allow user to search through their watch history (#3576)
* allow user to search through their watch history
* add tests for search in watch history
* Update client/src/app/shared/shared-main/users/user-history.service.ts
Diffstat (limited to 'client')
5 files changed, 58 insertions, 10 deletions
diff --git a/client/src/app/+my-library/my-history/my-history.component.html b/client/src/app/+my-library/my-history/my-history.component.html index 58b874ebf..c180161e7 100644 --- a/client/src/app/+my-library/my-history/my-history.component.html +++ b/client/src/app/+my-library/my-history/my-history.component.html | |||
@@ -1,12 +1,23 @@ | |||
1 | <h1> | 1 | <h1> |
2 | <my-global-icon iconName="history" aria-hidden="true"></my-global-icon> | 2 | <my-global-icon iconName="history" aria-hidden="true"></my-global-icon> |
3 | <ng-container i18n>My history</ng-container> | 3 | <ng-container i18n>My watch history</ng-container> <span class="badge badge-secondary">{{ pagination.totalItems }}</span> |
4 | </h1> | 4 | </h1> |
5 | 5 | ||
6 | <div class="top-buttons"> | 6 | <div class="top-buttons"> |
7 | <div class="history-switch"> | 7 | <div> |
8 | <div class="input-group has-feedback has-clear"> | ||
9 | <input | ||
10 | type="text" name="history-search" id="history-search" i18n-placeholder placeholder="Search your history" | ||
11 | (keyup)="onSearch($event)" | ||
12 | > | ||
13 | <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a> | ||
14 | <span class="sr-only" i18n>Clear filters</span> | ||
15 | </div> | ||
16 | </div> | ||
17 | |||
18 | <div class="history-switch ml-auto mr-3"> | ||
8 | <my-input-switch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></my-input-switch> | 19 | <my-input-switch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></my-input-switch> |
9 | <label i18n>Video history</label> | 20 | <label i18n>Track watch history</label> |
10 | </div> | 21 | </div> |
11 | 22 | ||
12 | <button class="delete-history" (click)="deleteHistory()" i18n> | 23 | <button class="delete-history" (click)="deleteHistory()" i18n> |
@@ -16,7 +27,7 @@ | |||
16 | </div> | 27 | </div> |
17 | 28 | ||
18 | 29 | ||
19 | <div class="no-history" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">You don't have any video history yet.</div> | 30 | <div class="no-history" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">You don't have any video in your watch history yet.</div> |
20 | 31 | ||
21 | <div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" class="videos"> | 32 | <div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" class="videos"> |
22 | <div class="video" *ngFor="let video of videos"> | 33 | <div class="video" *ngFor="let video of videos"> |
diff --git a/client/src/app/+my-library/my-history/my-history.component.scss b/client/src/app/+my-library/my-history/my-history.component.scss index 9eeeaf310..928a8a3da 100644 --- a/client/src/app/+my-library/my-history/my-history.component.scss +++ b/client/src/app/+my-library/my-history/my-history.component.scss | |||
@@ -10,17 +10,23 @@ | |||
10 | } | 10 | } |
11 | 11 | ||
12 | .top-buttons { | 12 | .top-buttons { |
13 | margin-bottom: 20px; | 13 | margin-bottom: 30px; |
14 | display: flex; | 14 | display: flex; |
15 | align-items: center; | 15 | align-items: center; |
16 | flex-wrap: wrap; | 16 | flex-wrap: wrap; |
17 | 17 | ||
18 | #history-search { | ||
19 | @include peertube-input-text(250px); | ||
20 | } | ||
21 | |||
18 | .history-switch { | 22 | .history-switch { |
19 | display: flex; | 23 | display: flex; |
20 | flex-grow: 1; | ||
21 | 24 | ||
22 | label { | 25 | label { |
23 | margin: 0 0 0 5px; | 26 | margin: 0 0 0 5px; |
27 | color: var(--greyForegroundColor); | ||
28 | font-size: 15px; | ||
29 | font-weight: $font-semibold; | ||
24 | } | 30 | } |
25 | } | 31 | } |
26 | 32 | ||
diff --git a/client/src/app/+my-library/my-history/my-history.component.ts b/client/src/app/+my-library/my-history/my-history.component.ts index 4ba95124d..0c8e4b83f 100644 --- a/client/src/app/+my-library/my-history/my-history.component.ts +++ b/client/src/app/+my-library/my-history/my-history.component.ts | |||
@@ -13,6 +13,8 @@ import { | |||
13 | import { immutableAssign } from '@app/helpers' | 13 | import { immutableAssign } from '@app/helpers' |
14 | import { UserHistoryService } from '@app/shared/shared-main' | 14 | import { UserHistoryService } from '@app/shared/shared-main' |
15 | import { AbstractVideoList } from '@app/shared/shared-video-miniature' | 15 | import { AbstractVideoList } from '@app/shared/shared-video-miniature' |
16 | import { Subject } from 'rxjs' | ||
17 | import { debounceTime, tap, distinctUntilChanged } from 'rxjs/operators' | ||
16 | 18 | ||
17 | @Component({ | 19 | @Component({ |
18 | templateUrl: './my-history.component.html', | 20 | templateUrl: './my-history.component.html', |
@@ -26,6 +28,9 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD | |||
26 | totalItems: null | 28 | totalItems: null |
27 | } | 29 | } |
28 | videosHistoryEnabled: boolean | 30 | videosHistoryEnabled: boolean |
31 | search: string | ||
32 | |||
33 | protected searchStream: Subject<string> | ||
29 | 34 | ||
30 | constructor ( | 35 | constructor ( |
31 | protected router: Router, | 36 | protected router: Router, |
@@ -41,7 +46,7 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD | |||
41 | ) { | 46 | ) { |
42 | super() | 47 | super() |
43 | 48 | ||
44 | this.titlePage = $localize`My videos history` | 49 | this.titlePage = $localize`My watch history` |
45 | } | 50 | } |
46 | 51 | ||
47 | ngOnInit () { | 52 | ngOnInit () { |
@@ -52,6 +57,28 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD | |||
52 | this.videosHistoryEnabled = this.authService.getUser().videosHistoryEnabled | 57 | this.videosHistoryEnabled = this.authService.getUser().videosHistoryEnabled |
53 | }) | 58 | }) |
54 | 59 | ||
60 | this.searchStream = new Subject() | ||
61 | |||
62 | this.searchStream | ||
63 | .pipe( | ||
64 | debounceTime(400), | ||
65 | distinctUntilChanged() | ||
66 | ) | ||
67 | .subscribe(search => { | ||
68 | this.search = search | ||
69 | this.reloadVideos() | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | onSearch (event: Event) { | ||
74 | const target = event.target as HTMLInputElement | ||
75 | this.searchStream.next(target.value) | ||
76 | } | ||
77 | |||
78 | resetSearch () { | ||
79 | const searchInput = document.getElementById('history-search') as HTMLInputElement | ||
80 | searchInput.value = '' | ||
81 | this.searchStream.next('') | ||
55 | } | 82 | } |
56 | 83 | ||
57 | ngOnDestroy () { | 84 | ngOnDestroy () { |
@@ -61,7 +88,10 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD | |||
61 | getVideosObservable (page: number) { | 88 | getVideosObservable (page: number) { |
62 | const newPagination = immutableAssign(this.pagination, { currentPage: page }) | 89 | const newPagination = immutableAssign(this.pagination, { currentPage: page }) |
63 | 90 | ||
64 | return this.userHistoryService.getUserVideosHistory(newPagination) | 91 | return this.userHistoryService.getUserVideosHistory(newPagination, this.search) |
92 | .pipe( | ||
93 | tap(res => this.pagination.totalItems = res.total) | ||
94 | ) | ||
65 | } | 95 | } |
66 | 96 | ||
67 | generateSyndicationList () { | 97 | generateSyndicationList () { |
diff --git a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html index 6ab3826ba..510b400c0 100644 --- a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html +++ b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html | |||
@@ -15,7 +15,7 @@ | |||
15 | </div> | 15 | </div> |
16 | </div> | 16 | </div> |
17 | 17 | ||
18 | <div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscriptions yet.</div> | 18 | <div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscription yet.</div> |
19 | 19 | ||
20 | <div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()"> | 20 | <div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()"> |
21 | <div *ngFor="let videoChannel of videoChannels" class="video-channel"> | 21 | <div *ngFor="let videoChannel of videoChannels" class="video-channel"> |
diff --git a/client/src/app/shared/shared-main/users/user-history.service.ts b/client/src/app/shared/shared-main/users/user-history.service.ts index 43970dc5b..bb87dcba8 100644 --- a/client/src/app/shared/shared-main/users/user-history.service.ts +++ b/client/src/app/shared/shared-main/users/user-history.service.ts | |||
@@ -18,11 +18,12 @@ export class UserHistoryService { | |||
18 | private videoService: VideoService | 18 | private videoService: VideoService |
19 | ) {} | 19 | ) {} |
20 | 20 | ||
21 | getUserVideosHistory (historyPagination: ComponentPaginationLight) { | 21 | getUserVideosHistory (historyPagination: ComponentPaginationLight, search?: string) { |
22 | const pagination = this.restService.componentPaginationToRestPagination(historyPagination) | 22 | const pagination = this.restService.componentPaginationToRestPagination(historyPagination) |
23 | 23 | ||
24 | let params = new HttpParams() | 24 | let params = new HttpParams() |
25 | params = this.restService.addRestGetParams(params, pagination) | 25 | params = this.restService.addRestGetParams(params, pagination) |
26 | params = params.append('search', search) | ||
26 | 27 | ||
27 | return this.authHttp | 28 | return this.authHttp |
28 | .get<ResultList<Video>>(UserHistoryService.BASE_USER_VIDEOS_HISTORY_URL, { params }) | 29 | .get<ResultList<Video>>(UserHistoryService.BASE_USER_VIDEOS_HISTORY_URL, { params }) |