aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/search
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/search')
-rw-r--r--client/src/app/search/search.component.html19
-rw-r--r--client/src/app/search/search.component.scss36
-rw-r--r--client/src/app/search/search.component.ts26
-rw-r--r--client/src/app/search/search.service.ts44
4 files changed, 99 insertions, 26 deletions
diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html
index bbc70f772..128cc52f5 100644
--- a/client/src/app/search/search.component.html
+++ b/client/src/app/search/search.component.html
@@ -22,10 +22,27 @@
22 </div> 22 </div>
23 </div> 23 </div>
24 24
25 <div i18n *ngIf="pagination.totalItems === 0" class="no-result"> 25 <div i18n *ngIf="pagination.totalItems === 0 && videoChannels.length === 0" class="no-result">
26 No results found 26 No results found
27 </div> 27 </div>
28 28
29 <div *ngFor="let videoChannel of videoChannels" class="entry video-channel">
30 <a [routerLink]="[ '/video-channels', videoChannel.name ]">
31 <img [src]="videoChannel.avatarUrl" alt="Avatar" />
32 </a>
33
34 <div class="video-channel-info">
35 <a [routerLink]="[ '/video-channels', videoChannel.name ]" class="video-channel-names">
36 <div class="video-channel-display-name">{{ videoChannel.displayName }}</div>
37 <div class="video-channel-name">{{ videoChannel.name }}</div>
38 </a>
39
40 <div i18n class="video-channel-followers">{{ videoChannel.followersCount }} subscribers</div>
41 </div>
42
43 <my-subscribe-button [videoChannel]="videoChannel"></my-subscribe-button>
44 </div>
45
29 <div *ngFor="let video of videos" class="entry video"> 46 <div *ngFor="let video of videos" class="entry video">
30 <my-video-thumbnail [video]="video"></my-video-thumbnail> 47 <my-video-thumbnail [video]="video"></my-video-thumbnail>
31 48
diff --git a/client/src/app/search/search.component.scss b/client/src/app/search/search.component.scss
index e54a8b32a..be7dd39cf 100644
--- a/client/src/app/search/search.component.scss
+++ b/client/src/app/search/search.component.scss
@@ -103,6 +103,42 @@
103 } 103 }
104 } 104 }
105 } 105 }
106
107 &.video-channel {
108
109 img {
110 @include avatar(120px);
111
112 margin: 0 50px 0 40px;
113 }
114
115 .video-channel-info {
116
117
118 flex-grow: 1;
119 width: fit-content;
120
121 .video-channel-names {
122 @include disable-default-a-behaviour;
123
124 display: flex;
125 align-items: baseline;
126 color: #000;
127 width: fit-content;
128
129 .video-channel-display-name {
130 font-weight: $font-semibold;
131 font-size: 18px;
132 }
133
134 .video-channel-name {
135 font-size: 14px;
136 color: $grey-actor-name;
137 margin-left: 5px;
138 }
139 }
140 }
141 }
106 } 142 }
107} 143}
108 144
diff --git a/client/src/app/search/search.component.ts b/client/src/app/search/search.component.ts
index 8d615fd05..f88df6391 100644
--- a/client/src/app/search/search.component.ts
+++ b/client/src/app/search/search.component.ts
@@ -2,13 +2,15 @@ import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { RedirectService } from '@app/core' 3import { RedirectService } from '@app/core'
4import { NotificationsService } from 'angular2-notifications' 4import { NotificationsService } from 'angular2-notifications'
5import { Subscription } from 'rxjs' 5import { forkJoin, Subscription } from 'rxjs'
6import { SearchService } from '@app/search/search.service' 6import { SearchService } from '@app/search/search.service'
7import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 7import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
8import { I18n } from '@ngx-translate/i18n-polyfill' 8import { I18n } from '@ngx-translate/i18n-polyfill'
9import { Video } from '../../../../shared' 9import { Video } from '../../../../shared'
10import { MetaService } from '@ngx-meta/core' 10import { MetaService } from '@ngx-meta/core'
11import { AdvancedSearch } from '@app/search/advanced-search.model' 11import { AdvancedSearch } from '@app/search/advanced-search.model'
12import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
13import { immutableAssign } from '@app/shared/misc/utils'
12 14
13@Component({ 15@Component({
14 selector: 'my-search', 16 selector: 'my-search',
@@ -17,18 +19,22 @@ import { AdvancedSearch } from '@app/search/advanced-search.model'
17}) 19})
18export class SearchComponent implements OnInit, OnDestroy { 20export class SearchComponent implements OnInit, OnDestroy {
19 videos: Video[] = [] 21 videos: Video[] = []
22 videoChannels: VideoChannel[] = []
23
20 pagination: ComponentPagination = { 24 pagination: ComponentPagination = {
21 currentPage: 1, 25 currentPage: 1,
22 itemsPerPage: 10, // It's per object type (so 10 videos, 10 video channels etc) 26 itemsPerPage: 10, // Only for videos, use another variable for channels
23 totalItems: null 27 totalItems: null
24 } 28 }
25 advancedSearch: AdvancedSearch = new AdvancedSearch() 29 advancedSearch: AdvancedSearch = new AdvancedSearch()
26 isSearchFilterCollapsed = true 30 isSearchFilterCollapsed = true
31 currentSearch: string
27 32
28 private subActivatedRoute: Subscription 33 private subActivatedRoute: Subscription
29 private currentSearch: string
30 private isInitialLoad = true 34 private isInitialLoad = true
31 35
36 private channelsPerPage = 2
37
32 constructor ( 38 constructor (
33 private i18n: I18n, 39 private i18n: I18n,
34 private route: ActivatedRoute, 40 private route: ActivatedRoute,
@@ -74,17 +80,23 @@ export class SearchComponent implements OnInit, OnDestroy {
74 } 80 }
75 81
76 search () { 82 search () {
77 return this.searchService.searchVideos(this.currentSearch, this.pagination, this.advancedSearch) 83 forkJoin([
84 this.searchService.searchVideos(this.currentSearch, this.pagination, this.advancedSearch),
85 this.searchService.searchVideoChannels(this.currentSearch, immutableAssign(this.pagination, { itemsPerPage: this.channelsPerPage }))
86 ])
78 .subscribe( 87 .subscribe(
79 ({ videos, totalVideos }) => { 88 ([ videosResult, videoChannelsResult ]) => {
80 this.videos = this.videos.concat(videos) 89 this.videos = this.videos.concat(videosResult.videos)
81 this.pagination.totalItems = totalVideos 90 this.pagination.totalItems = videosResult.totalVideos
91
92 this.videoChannels = videoChannelsResult.data
82 }, 93 },
83 94
84 error => { 95 error => {
85 this.notificationsService.error(this.i18n('Error'), error.message) 96 this.notificationsService.error(this.i18n('Error'), error.message)
86 } 97 }
87 ) 98 )
99
88 } 100 }
89 101
90 onNearOfBottom () { 102 onNearOfBottom () {
diff --git a/client/src/app/search/search.service.ts b/client/src/app/search/search.service.ts
index a37c49161..cd3bdad35 100644
--- a/client/src/app/search/search.service.ts
+++ b/client/src/app/search/search.service.ts
@@ -1,4 +1,4 @@
1import { catchError, switchMap } from 'rxjs/operators' 1import { catchError, map, switchMap } from 'rxjs/operators'
2import { HttpClient, HttpParams } from '@angular/common/http' 2import { HttpClient, HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core' 3import { Injectable } from '@angular/core'
4import { Observable } from 'rxjs' 4import { Observable } from 'rxjs'
@@ -6,13 +6,11 @@ import { ComponentPagination } from '@app/shared/rest/component-pagination.model
6import { VideoService } from '@app/shared/video/video.service' 6import { VideoService } from '@app/shared/video/video.service'
7import { RestExtractor, RestService } from '@app/shared' 7import { RestExtractor, RestService } from '@app/shared'
8import { environment } from 'environments/environment' 8import { environment } from 'environments/environment'
9import { ResultList, Video } from '../../../../shared' 9import { ResultList, Video as VideoServerModel, VideoChannel as VideoChannelServerModel } from '../../../../shared'
10import { Video as VideoServerModel } from '@app/shared/video/video.model' 10import { Video } from '@app/shared/video/video.model'
11import { AdvancedSearch } from '@app/search/advanced-search.model' 11import { AdvancedSearch } from '@app/search/advanced-search.model'
12 12import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
13export type SearchResult = { 13import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
14 videosResult: { totalVideos: number, videos: Video[] }
15}
16 14
17@Injectable() 15@Injectable()
18export class SearchService { 16export class SearchService {
@@ -40,17 +38,7 @@ export class SearchService {
40 if (search) params = params.append('search', search) 38 if (search) params = params.append('search', search)
41 39
42 const advancedSearchObject = advancedSearch.toAPIObject() 40 const advancedSearchObject = advancedSearch.toAPIObject()
43 41 params = this.restService.addObjectParams(params, advancedSearchObject)
44 for (const name of Object.keys(advancedSearchObject)) {
45 const value = advancedSearchObject[name]
46 if (!value) continue
47
48 if (Array.isArray(value) && value.length !== 0) {
49 for (const v of value) params = params.append(name, v)
50 } else {
51 params = params.append(name, value)
52 }
53 }
54 42
55 return this.authHttp 43 return this.authHttp
56 .get<ResultList<VideoServerModel>>(url, { params }) 44 .get<ResultList<VideoServerModel>>(url, { params })
@@ -59,4 +47,24 @@ export class SearchService {
59 catchError(err => this.restExtractor.handleError(err)) 47 catchError(err => this.restExtractor.handleError(err))
60 ) 48 )
61 } 49 }
50
51 searchVideoChannels (
52 search: string,
53 componentPagination: ComponentPagination
54 ): Observable<{ data: VideoChannel[], total: number }> {
55 const url = SearchService.BASE_SEARCH_URL + 'video-channels'
56
57 const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
58
59 let params = new HttpParams()
60 params = this.restService.addRestGetParams(params, pagination)
61 params = params.append('search', search)
62
63 return this.authHttp
64 .get<ResultList<VideoChannelServerModel>>(url, { params })
65 .pipe(
66 map(res => VideoChannelService.extractVideoChannels(res)),
67 catchError(err => this.restExtractor.handleError(err))
68 )
69 }
62} 70}