aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html2
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss7
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts18
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.html4
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.scss11
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.ts25
-rw-r--r--client/src/app/shared/users/user.service.ts2
-rw-r--r--client/src/app/shared/video-playlist/video-add-to-playlist.component.html2
-rw-r--r--client/src/app/shared/video/abstract-video-list.ts2
-rw-r--r--client/src/app/shared/video/video-miniature.component.scss3
-rw-r--r--client/src/app/shared/video/video.service.ts5
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comments.component.scss1
-rw-r--r--client/src/sass/primeng-custom.scss6
-rw-r--r--server/controllers/api/users/me.ts3
-rw-r--r--server/models/video/video.ts24
15 files changed, 98 insertions, 17 deletions
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html
index 307884c70..878772359 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html
@@ -1,4 +1,6 @@
1<div class="video-playlists-header"> 1<div class="video-playlists-header">
2 <input type="text" placeholder="Search your playlists" i18n-placeholder [(ngModel)]="videoPlaylistsSearch" (ngModelChange)="onVideoPlaylistSearchChanged()" />
3
2 <a class="create-button" routerLink="create"> 4 <a class="create-button" routerLink="create">
3 <my-global-icon iconName="add"></my-global-icon> 5 <my-global-icon iconName="add"></my-global-icon>
4 <ng-container i18n>Create a new playlist</ng-container> 6 <ng-container i18n>Create a new playlist</ng-container>
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss
index d5635417d..4fb4ed4be 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss
@@ -29,12 +29,19 @@
29 29
30 .video-playlist-buttons { 30 .video-playlist-buttons {
31 min-width: 190px; 31 min-width: 190px;
32 height: max-content;
32 } 33 }
33} 34}
34 35
35.video-playlists-header { 36.video-playlists-header {
37 display: flex;
38 justify-content: space-between;
36 text-align: right; 39 text-align: right;
37 margin: 20px 0 50px; 40 margin: 20px 0 50px;
41
42 input[type=text] {
43 @include peertube-input-text(300px);
44 }
38} 45}
39 46
40@media screen and (max-width: 800px) { 47@media screen and (max-width: 800px) {
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts
index 76b13fe2b..42e4782eb 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts
@@ -3,7 +3,7 @@ import { Notifier } from '@app/core'
3import { AuthService } from '../../core/auth' 3import { AuthService } from '../../core/auth'
4import { ConfirmService } from '../../core/confirm' 4import { ConfirmService } from '../../core/confirm'
5import { User } from '@app/shared' 5import { User } from '@app/shared'
6import { flatMap } from 'rxjs/operators' 6import { flatMap, debounceTime } from 'rxjs/operators'
7import { I18n } from '@ngx-translate/i18n-polyfill' 7import { I18n } from '@ngx-translate/i18n-polyfill'
8import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' 8import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
9import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 9import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
@@ -17,7 +17,9 @@ import { Subject } from 'rxjs'
17 styleUrls: [ './my-account-video-playlists.component.scss' ] 17 styleUrls: [ './my-account-video-playlists.component.scss' ]
18}) 18})
19export class MyAccountVideoPlaylistsComponent implements OnInit { 19export class MyAccountVideoPlaylistsComponent implements OnInit {
20 videoPlaylistsSearch: string
20 videoPlaylists: VideoPlaylist[] = [] 21 videoPlaylists: VideoPlaylist[] = []
22 videoPlaylistSearchChanged = new Subject<string>()
21 23
22 pagination: ComponentPagination = { 24 pagination: ComponentPagination = {
23 currentPage: 1, 25 currentPage: 1,
@@ -41,6 +43,13 @@ export class MyAccountVideoPlaylistsComponent implements OnInit {
41 this.user = this.authService.getUser() 43 this.user = this.authService.getUser()
42 44
43 this.loadVideoPlaylists() 45 this.loadVideoPlaylists()
46
47 this.videoPlaylistSearchChanged
48 .pipe(
49 debounceTime(500))
50 .subscribe(() => {
51 this.loadVideoPlaylists()
52 })
44 } 53 }
45 54
46 async deleteVideoPlaylist (videoPlaylist: VideoPlaylist) { 55 async deleteVideoPlaylist (videoPlaylist: VideoPlaylist) {
@@ -80,12 +89,17 @@ export class MyAccountVideoPlaylistsComponent implements OnInit {
80 this.loadVideoPlaylists() 89 this.loadVideoPlaylists()
81 } 90 }
82 91
92 onVideoPlaylistSearchChanged () {
93 this.videoPlaylistSearchChanged.next()
94 }
95
83 private loadVideoPlaylists () { 96 private loadVideoPlaylists () {
84 this.authService.userInformationLoaded 97 this.authService.userInformationLoaded
85 .pipe(flatMap(() => { 98 .pipe(flatMap(() => {
86 return this.videoPlaylistService.listAccountPlaylists(this.user.account, this.pagination, '-updatedAt') 99 return this.videoPlaylistService.listAccountPlaylists(this.user.account, this.pagination, '-updatedAt', this.videoPlaylistsSearch)
87 })) 100 }))
88 .subscribe(res => { 101 .subscribe(res => {
102 this.videoPlaylists = []
89 this.videoPlaylists = this.videoPlaylists.concat(res.data) 103 this.videoPlaylists = this.videoPlaylists.concat(res.data)
90 this.pagination.totalItems = res.total 104 this.pagination.totalItems = res.total
91 105
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
index 2854093c4..a898cd938 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
@@ -1,3 +1,7 @@
1<div class="videos-header">
2 <input type="text" placeholder="Search your videos" i18n-placeholder [(ngModel)]="videosSearch" (ngModelChange)="onVideosSearchChanged()" />
3</div>
4
1<my-videos-selection 5<my-videos-selection
2 [pagination]="pagination" 6 [pagination]="pagination"
3 [(selection)]="selection" 7 [(selection)]="selection"
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
index 87398e7c8..44545b3e1 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
@@ -1,6 +1,17 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3 3
4.videos-header {
5 display: flex;
6 justify-content: space-between;
7 text-align: right;
8 margin: 20px 0 50px;
9
10 input[type=text] {
11 @include peertube-input-text(300px);
12 }
13}
14
4.action-button-delete-selection { 15.action-button-delete-selection {
5 display: inline-block; 16 display: inline-block;
6 17
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
index 2c86a3c56..dd4b25d08 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
@@ -1,6 +1,6 @@
1import { concat, Observable } from 'rxjs' 1import { concat, Observable, Subject } from 'rxjs'
2import { tap, toArray } from 'rxjs/operators' 2import { tap, toArray, debounceTime } from 'rxjs/operators'
3import { Component, ViewChild } from '@angular/core' 3import { Component, ViewChild, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { immutableAssign } from '@app/shared/misc/utils' 5import { immutableAssign } from '@app/shared/misc/utils'
6import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 6import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
@@ -22,7 +22,7 @@ import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
22 templateUrl: './my-account-videos.component.html', 22 templateUrl: './my-account-videos.component.html',
23 styleUrls: [ './my-account-videos.component.scss' ] 23 styleUrls: [ './my-account-videos.component.scss' ]
24}) 24})
25export class MyAccountVideosComponent implements DisableForReuseHook { 25export class MyAccountVideosComponent implements OnInit, DisableForReuseHook {
26 @ViewChild('videosSelection', { static: true }) videosSelection: VideosSelectionComponent 26 @ViewChild('videosSelection', { static: true }) videosSelection: VideosSelectionComponent
27 @ViewChild('videoChangeOwnershipModal', { static: true }) videoChangeOwnershipModal: VideoChangeOwnershipComponent 27 @ViewChild('videoChangeOwnershipModal', { static: true }) videoChangeOwnershipModal: VideoChangeOwnershipComponent
28 28
@@ -43,6 +43,8 @@ export class MyAccountVideosComponent implements DisableForReuseHook {
43 blacklistInfo: true 43 blacklistInfo: true
44 } 44 }
45 videos: Video[] = [] 45 videos: Video[] = []
46 videosSearch: string
47 videosSearchChanged = new Subject<string>()
46 getVideosObservableFunction = this.getVideosObservable.bind(this) 48 getVideosObservableFunction = this.getVideosObservable.bind(this)
47 49
48 constructor ( 50 constructor (
@@ -59,6 +61,19 @@ export class MyAccountVideosComponent implements DisableForReuseHook {
59 this.titlePage = this.i18n('My videos') 61 this.titlePage = this.i18n('My videos')
60 } 62 }
61 63
64 ngOnInit () {
65 this.videosSearchChanged
66 .pipe(
67 debounceTime(500))
68 .subscribe(() => {
69 this.videosSelection.reloadVideos()
70 })
71 }
72
73 onVideosSearchChanged () {
74 this.videosSearchChanged.next()
75 }
76
62 disableForReuse () { 77 disableForReuse () {
63 this.videosSelection.disableForReuse() 78 this.videosSelection.disableForReuse()
64 } 79 }
@@ -70,7 +85,7 @@ export class MyAccountVideosComponent implements DisableForReuseHook {
70 getVideosObservable (page: number, sort: VideoSortField) { 85 getVideosObservable (page: number, sort: VideoSortField) {
71 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 86 const newPagination = immutableAssign(this.pagination, { currentPage: page })
72 87
73 return this.videoService.getMyVideos(newPagination, sort) 88 return this.videoService.getMyVideos(newPagination, sort, this.videosSearch)
74 } 89 }
75 90
76 async deleteSelectedVideos () { 91 async deleteSelectedVideos () {
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index 41ee87197..051e0bfa4 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -88,7 +88,7 @@ export class UserService {
88 } 88 }
89 89
90 getMyVideoQuotaUsed () { 90 getMyVideoQuotaUsed () {
91 const url = UserService.BASE_USERS_URL + '/me/video-quota-used' 91 const url = UserService.BASE_USERS_URL + 'me/video-quota-used'
92 92
93 return this.authHttp.get<UserVideoQuota>(url) 93 return this.authHttp.get<UserVideoQuota>(url)
94 .pipe(catchError(err => this.restExtractor.handleError(err))) 94 .pipe(catchError(err => this.restExtractor.handleError(err)))
diff --git a/client/src/app/shared/video-playlist/video-add-to-playlist.component.html b/client/src/app/shared/video-playlist/video-add-to-playlist.component.html
index ba30953b9..6e0989227 100644
--- a/client/src/app/shared/video-playlist/video-add-to-playlist.component.html
+++ b/client/src/app/shared/video-playlist/video-add-to-playlist.component.html
@@ -42,7 +42,7 @@
42 </div> 42 </div>
43 43
44 <div class="input-container"> 44 <div class="input-container">
45 <input type="text" placeholder="Search playlists" [(ngModel)]="videoPlaylistSearch" (ngModelChange)="onVideoPlaylistSearchChanged()" /> 45 <input type="text" placeholder="Search playlists" i18n-placeholder [(ngModel)]="videoPlaylistSearch" (ngModelChange)="onVideoPlaylistSearchChanged()" />
46 </div> 46 </div>
47 47
48 <div class="playlists"> 48 <div class="playlists">
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts
index a2a12bec7..746359851 100644
--- a/client/src/app/shared/video/abstract-video-list.ts
+++ b/client/src/app/shared/video/abstract-video-list.ts
@@ -150,6 +150,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
150 this.getVideosObservable(this.pagination.currentPage).subscribe( 150 this.getVideosObservable(this.pagination.currentPage).subscribe(
151 ({ data, total }) => { 151 ({ data, total }) => {
152 this.pagination.totalItems = total 152 this.pagination.totalItems = total
153 this.videos = []
153 this.videos = this.videos.concat(data) 154 this.videos = this.videos.concat(data)
154 155
155 if (this.groupByDate) this.buildGroupedDateLabels() 156 if (this.groupByDate) this.buildGroupedDateLabels()
@@ -170,7 +171,6 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
170 171
171 reloadVideos () { 172 reloadVideos () {
172 this.pagination.currentPage = 1 173 this.pagination.currentPage = 1
173 this.videos = []
174 this.loadMoreVideos() 174 this.loadMoreVideos()
175 } 175 }
176 176
diff --git a/client/src/app/shared/video/video-miniature.component.scss b/client/src/app/shared/video/video-miniature.component.scss
index 3988cc055..ac83c5dfa 100644
--- a/client/src/app/shared/video/video-miniature.component.scss
+++ b/client/src/app/shared/video/video-miniature.component.scss
@@ -100,7 +100,8 @@ $more-margin-right: 15px;
100 flex-direction: row; 100 flex-direction: row;
101 margin-bottom: 0; 101 margin-bottom: 0;
102 height: auto; 102 height: auto;
103 width: 100%; 103 display: flex;
104 flex-grow: 1;
104 105
105 my-video-thumbnail { 106 my-video-thumbnail {
106 margin-right: 10px; 107 margin-right: 10px;
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index 9adf46495..2dd47d74e 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -121,14 +121,15 @@ export class VideoService implements VideosProvider {
121 .pipe(catchError(err => this.restExtractor.handleError(err))) 121 .pipe(catchError(err => this.restExtractor.handleError(err)))
122 } 122 }
123 123
124 getMyVideos (videoPagination: ComponentPagination, sort: VideoSortField): Observable<ResultList<Video>> { 124 getMyVideos (videoPagination: ComponentPagination, sort: VideoSortField, search?: string): Observable<ResultList<Video>> {
125 const pagination = this.restService.componentPaginationToRestPagination(videoPagination) 125 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
126 126
127 let params = new HttpParams() 127 let params = new HttpParams()
128 params = this.restService.addRestGetParams(params, pagination, sort) 128 params = this.restService.addRestGetParams(params, pagination, sort)
129 params = this.restService.addObjectParams(params, { search })
129 130
130 return this.authHttp 131 return this.authHttp
131 .get<ResultList<Video>>(UserService.BASE_USERS_URL + '/me/videos', { params }) 132 .get<ResultList<Video>>(UserService.BASE_USERS_URL + 'me/videos', { params })
132 .pipe( 133 .pipe(
133 switchMap(res => this.extractVideos(res)), 134 switchMap(res => this.extractVideos(res)),
134 catchError(err => this.restExtractor.handleError(err)) 135 catchError(err => this.restExtractor.handleError(err))
diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.scss b/client/src/app/videos/+video-watch/comment/video-comments.component.scss
index 9e3682295..c02f6c21b 100644
--- a/client/src/app/videos/+video-watch/comment/video-comments.component.scss
+++ b/client/src/app/videos/+video-watch/comment/video-comments.component.scss
@@ -27,6 +27,7 @@
27 font-weight: 600; 27 font-weight: 600;
28 text-transform: uppercase; 28 text-transform: uppercase;
29 border: none; 29 border: none;
30 transform: translateY(-7%);
30} 31}
31 32
32my-feed { 33my-feed {
diff --git a/client/src/sass/primeng-custom.scss b/client/src/sass/primeng-custom.scss
index 0acffef3c..9398f0adc 100644
--- a/client/src/sass/primeng-custom.scss
+++ b/client/src/sass/primeng-custom.scss
@@ -10,6 +10,12 @@
10 color: var(--mainForegroundColor) !important; 10 color: var(--mainForegroundColor) !important;
11} 11}
12 12
13my-edit-button,
14my-delete-button,
15my-button {
16 height: max-content;
17}
18
13// data table customizations 19// data table customizations
14p-table { 20p-table {
15 .ui-table-caption { 21 .ui-table-caption {
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index ba976ab03..b1f29f252 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -99,7 +99,8 @@ async function getUserVideos (req: express.Request, res: express.Response) {
99 user.Account.id, 99 user.Account.id,
100 req.query.start as number, 100 req.query.start as number,
101 req.query.count as number, 101 req.query.count as number,
102 req.query.sort as VideoSortField 102 req.query.sort as VideoSortField,
103 req.query.search as string
103 ) 104 )
104 105
105 const additionalAttributes = { 106 const additionalAttributes = {
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 164122ee2..1f3c25ecb 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1196,9 +1196,15 @@ export class VideoModel extends Model<VideoModel> {
1196 }) 1196 })
1197 } 1197 }
1198 1198
1199 static listUserVideosForApi (accountId: number, start: number, count: number, sort: string) { 1199 static listUserVideosForApi (
1200 accountId: number,
1201 start: number,
1202 count: number,
1203 sort: string,
1204 search?: string
1205 ) {
1200 function buildBaseQuery (): FindOptions { 1206 function buildBaseQuery (): FindOptions {
1201 return { 1207 let baseQuery = {
1202 offset: start, 1208 offset: start,
1203 limit: count, 1209 limit: count,
1204 order: getVideoSort(sort), 1210 order: getVideoSort(sort),
@@ -1218,12 +1224,24 @@ export class VideoModel extends Model<VideoModel> {
1218 } 1224 }
1219 ] 1225 ]
1220 } 1226 }
1227
1228 if (search) {
1229 baseQuery = Object.assign(baseQuery, {
1230 where: {
1231 name: {
1232 [ Op.iLike ]: '%' + search + '%'
1233 }
1234 }
1235 })
1236 }
1237
1238 return baseQuery
1221 } 1239 }
1222 1240
1223 const countQuery = buildBaseQuery() 1241 const countQuery = buildBaseQuery()
1224 const findQuery = buildBaseQuery() 1242 const findQuery = buildBaseQuery()
1225 1243
1226 const findScopes = [ 1244 const findScopes: (string | ScopeOptions)[] = [
1227 ScopeNames.WITH_SCHEDULED_UPDATE, 1245 ScopeNames.WITH_SCHEDULED_UPDATE,
1228 ScopeNames.WITH_BLACKLISTED, 1246 ScopeNames.WITH_BLACKLISTED,
1229 ScopeNames.WITH_THUMBNAILS 1247 ScopeNames.WITH_THUMBNAILS