Fix client search
This commit is contained in:
parent
d235f6b0d1
commit
f3aaa9a95c
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { AbstractVideoList } from '../../shared/video/abstract-video-list'
|
import { AbstractVideoList } from '../../shared/video/abstract-video-list'
|
||||||
|
@ -9,7 +9,7 @@ import { VideoService } from '../../shared/video/video.service'
|
||||||
templateUrl: './account-videos.component.html',
|
templateUrl: './account-videos.component.html',
|
||||||
styleUrls: [ './account-videos.component.scss' ]
|
styleUrls: [ './account-videos.component.scss' ]
|
||||||
})
|
})
|
||||||
export class AccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
|
export class AccountVideosComponent extends AbstractVideoList implements OnInit {
|
||||||
titlePage = 'My videos'
|
titlePage = 'My videos'
|
||||||
currentRoute = '/account/videos'
|
currentRoute = '/account/videos'
|
||||||
|
|
||||||
|
@ -24,10 +24,6 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit,
|
||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
|
||||||
super.ngOnDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
getVideosObservable () {
|
getVideosObservable () {
|
||||||
return this.videoService.getMyVideos(this.pagination, this.sort)
|
return this.videoService.getMyVideos(this.pagination, this.sort)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<my-search></my-search>
|
<my-header></my-header>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { SignupModule } from './signup'
|
||||||
import { SharedModule } from './shared'
|
import { SharedModule } from './shared'
|
||||||
import { VideosModule } from './videos'
|
import { VideosModule } from './videos'
|
||||||
import { MenuComponent, MenuAdminComponent } from './menu'
|
import { MenuComponent, MenuAdminComponent } from './menu'
|
||||||
|
import { HeaderComponent } from './header'
|
||||||
|
|
||||||
export function metaFactory (): MetaLoader {
|
export function metaFactory (): MetaLoader {
|
||||||
return new MetaStaticLoader({
|
return new MetaStaticLoader({
|
||||||
|
@ -51,7 +52,8 @@ const APP_PROVIDERS = [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
MenuAdminComponent
|
MenuAdminComponent,
|
||||||
|
HeaderComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<input
|
<input
|
||||||
type="text" id="search-video" name="search-video" placeholder="Search..."
|
type="text" id="search-video" name="search-video" placeholder="Search..."
|
||||||
[(ngModel)]="searchCriteria.value" (keyup.enter)="doSearch()"
|
[(ngModel)]="searchValue" (keyup.enter)="doSearch()"
|
||||||
>
|
>
|
||||||
<span (click)="doSearch()" class="icon icon-search"></span>
|
<span (click)="doSearch()" class="icon icon-search"></span>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Component, OnInit } from '@angular/core'
|
||||||
|
import { Router } from '@angular/router'
|
||||||
|
import { getParameterByName } from '../shared/misc/utils'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-header',
|
||||||
|
templateUrl: './header.component.html',
|
||||||
|
styleUrls: [ './header.component.scss' ]
|
||||||
|
})
|
||||||
|
|
||||||
|
export class HeaderComponent implements OnInit {
|
||||||
|
searchValue = ''
|
||||||
|
|
||||||
|
constructor (private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
const searchQuery = getParameterByName('search', window.location.href)
|
||||||
|
if (searchQuery) this.searchValue = searchQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
doSearch () {
|
||||||
|
if (!this.searchValue) return
|
||||||
|
|
||||||
|
this.router.navigate([ '/videos', 'search' ], {
|
||||||
|
queryParams: { search: this.searchValue }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './header.component'
|
|
@ -1,7 +1,6 @@
|
||||||
export * from './auth'
|
export * from './auth'
|
||||||
export * from './forms'
|
export * from './forms'
|
||||||
export * from './rest'
|
export * from './rest'
|
||||||
export * from './search'
|
|
||||||
export * from './users'
|
export * from './users'
|
||||||
export * from './video-abuse'
|
export * from './video-abuse'
|
||||||
export * from './video-blacklist'
|
export * from './video-blacklist'
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
|
||||||
|
|
||||||
|
function getParameterByName (name: string, url: string) {
|
||||||
|
if (!url) url = window.location.href
|
||||||
|
name = name.replace(/[\[\]]/g, '\\$&')
|
||||||
|
|
||||||
|
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
|
||||||
|
const results = regex.exec(url)
|
||||||
|
|
||||||
|
if (!results) return null
|
||||||
|
if (!results[2]) return ''
|
||||||
|
|
||||||
|
return decodeURIComponent(results[2].replace(/\+/g, ' '))
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getParameterByName
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
export * from './search-field.type'
|
|
||||||
export * from './search.component'
|
|
||||||
export * from './search.model'
|
|
||||||
export * from './search.service'
|
|
|
@ -1 +0,0 @@
|
||||||
export type SearchField = 'name' | 'account' | 'host' | 'tags'
|
|
|
@ -1,42 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
|
||||||
import { Router } from '@angular/router'
|
|
||||||
import { Search } from './search.model'
|
|
||||||
import { SearchService } from './search.service'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-search',
|
|
||||||
templateUrl: './search.component.html',
|
|
||||||
styleUrls: [ './search.component.scss' ]
|
|
||||||
})
|
|
||||||
|
|
||||||
export class SearchComponent implements OnInit {
|
|
||||||
searchCriteria: Search = {
|
|
||||||
field: 'name',
|
|
||||||
value: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor (private searchService: SearchService, private router: Router) {}
|
|
||||||
|
|
||||||
ngOnInit () {
|
|
||||||
// Subscribe if the search changed
|
|
||||||
// Usually changed by videos list component
|
|
||||||
this.searchService.updateSearch.subscribe(
|
|
||||||
newSearchCriteria => {
|
|
||||||
// Put a field by default
|
|
||||||
if (!newSearchCriteria.field) {
|
|
||||||
newSearchCriteria.field = 'name'
|
|
||||||
}
|
|
||||||
|
|
||||||
this.searchCriteria = newSearchCriteria
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
doSearch () {
|
|
||||||
// if (this.router.url.indexOf('/videos/list') === -1) {
|
|
||||||
// this.router.navigate([ '/videos/list' ])
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.searchService.searchUpdated.next(this.searchCriteria)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import { SearchField } from './search-field.type'
|
|
||||||
|
|
||||||
export interface Search {
|
|
||||||
field: SearchField
|
|
||||||
value: string
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { Injectable } from '@angular/core'
|
|
||||||
import { Subject } from 'rxjs/Subject'
|
|
||||||
import { ReplaySubject } from 'rxjs/ReplaySubject'
|
|
||||||
|
|
||||||
import { Search } from './search.model'
|
|
||||||
|
|
||||||
// This class is needed to communicate between videos/ and search component
|
|
||||||
// Remove it when we'll be able to subscribe to router changes
|
|
||||||
@Injectable()
|
|
||||||
export class SearchService {
|
|
||||||
searchUpdated: Subject<Search>
|
|
||||||
updateSearch: Subject<Search>
|
|
||||||
|
|
||||||
constructor () {
|
|
||||||
this.updateSearch = new Subject<Search>()
|
|
||||||
this.searchUpdated = new ReplaySubject<Search>(1)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ import { FromNowPipe } from './misc/from-now.pipe'
|
||||||
import { LoaderComponent } from './misc/loader.component'
|
import { LoaderComponent } from './misc/loader.component'
|
||||||
import { NumberFormatterPipe } from './misc/number-formatter.pipe'
|
import { NumberFormatterPipe } from './misc/number-formatter.pipe'
|
||||||
import { RestExtractor, RestService } from './rest'
|
import { RestExtractor, RestService } from './rest'
|
||||||
import { SearchComponent, SearchService } from './search'
|
|
||||||
import { UserService } from './users'
|
import { UserService } from './users'
|
||||||
import { VideoAbuseService } from './video-abuse'
|
import { VideoAbuseService } from './video-abuse'
|
||||||
import { VideoBlacklistService } from './video-blacklist'
|
import { VideoBlacklistService } from './video-blacklist'
|
||||||
|
@ -43,7 +42,6 @@ import { VideoService } from './video/video.service'
|
||||||
],
|
],
|
||||||
|
|
||||||
declarations: [
|
declarations: [
|
||||||
SearchComponent,
|
|
||||||
LoaderComponent,
|
LoaderComponent,
|
||||||
VideoThumbnailComponent,
|
VideoThumbnailComponent,
|
||||||
NumberFormatterPipe,
|
NumberFormatterPipe,
|
||||||
|
@ -66,7 +64,6 @@ import { VideoService } from './video/video.service'
|
||||||
BytesPipe,
|
BytesPipe,
|
||||||
KeysPipe,
|
KeysPipe,
|
||||||
|
|
||||||
SearchComponent,
|
|
||||||
LoaderComponent,
|
LoaderComponent,
|
||||||
VideoThumbnailComponent,
|
VideoThumbnailComponent,
|
||||||
|
|
||||||
|
@ -78,7 +75,6 @@ import { VideoService } from './video/video.service'
|
||||||
AUTH_INTERCEPTOR_PROVIDER,
|
AUTH_INTERCEPTOR_PROVIDER,
|
||||||
RestExtractor,
|
RestExtractor,
|
||||||
RestService,
|
RestService,
|
||||||
SearchService,
|
|
||||||
VideoAbuseService,
|
VideoAbuseService,
|
||||||
VideoBlacklistService,
|
VideoBlacklistService,
|
||||||
UserService,
|
UserService,
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import { OnDestroy, OnInit } from '@angular/core'
|
import { OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { Observable } from 'rxjs/Observable'
|
import { Observable } from 'rxjs/Observable'
|
||||||
import { Subscription } from 'rxjs/Subscription'
|
|
||||||
import { SortField } from './sort-field.type'
|
import { SortField } from './sort-field.type'
|
||||||
import { VideoPagination } from './video-pagination.model'
|
import { VideoPagination } from './video-pagination.model'
|
||||||
import { Video } from './video.model'
|
import { Video } from './video.model'
|
||||||
|
|
||||||
export abstract class AbstractVideoList implements OnInit, OnDestroy {
|
export abstract class AbstractVideoList implements OnInit {
|
||||||
pagination: VideoPagination = {
|
pagination: VideoPagination = {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
itemsPerPage: 25,
|
itemsPerPage: 25,
|
||||||
totalItems: null
|
totalItems: null
|
||||||
}
|
}
|
||||||
sort: SortField = '-createdAt'
|
sort: SortField = '-createdAt'
|
||||||
|
defaultSort: SortField = '-createdAt'
|
||||||
videos: Video[] = []
|
videos: Video[] = []
|
||||||
|
loadOnInit = true
|
||||||
|
|
||||||
protected notificationsService: NotificationsService
|
protected notificationsService: NotificationsService
|
||||||
protected router: Router
|
protected router: Router
|
||||||
protected route: ActivatedRoute
|
protected route: ActivatedRoute
|
||||||
protected subActivatedRoute: Subscription
|
|
||||||
|
|
||||||
protected abstract currentRoute: string
|
protected abstract currentRoute: string
|
||||||
|
|
||||||
|
@ -32,13 +32,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
|
||||||
// Subscribe to route changes
|
// Subscribe to route changes
|
||||||
const routeParams = this.route.snapshot.params
|
const routeParams = this.route.snapshot.params
|
||||||
this.loadRouteParams(routeParams)
|
this.loadRouteParams(routeParams)
|
||||||
this.loadMoreVideos('after')
|
if (this.loadOnInit === true) this.loadMoreVideos('after')
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy () {
|
|
||||||
if (this.subActivatedRoute) {
|
|
||||||
this.subActivatedRoute.unsubscribe()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onNearOfTop () {
|
onNearOfTop () {
|
||||||
|
@ -53,6 +47,12 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reloadVideos () {
|
||||||
|
this.videos = []
|
||||||
|
this.loadedPages = {}
|
||||||
|
this.loadMoreVideos('before')
|
||||||
|
}
|
||||||
|
|
||||||
loadMoreVideos (where: 'before' | 'after') {
|
loadMoreVideos (where: 'before' | 'after') {
|
||||||
if (this.loadedPages[this.pagination.currentPage] === true) return
|
if (this.loadedPages[this.pagination.currentPage] === true) return
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected loadRouteParams (routeParams: { [ key: string ]: any }) {
|
protected loadRouteParams (routeParams: { [ key: string ]: any }) {
|
||||||
this.sort = routeParams['sort'] as SortField || '-createdAt'
|
this.sort = routeParams['sort'] as SortField || this.defaultSort
|
||||||
|
|
||||||
if (routeParams['page'] !== undefined) {
|
if (routeParams['page'] !== undefined) {
|
||||||
this.pagination.currentPage = parseInt(routeParams['page'], 10)
|
this.pagination.currentPage = parseInt(routeParams['page'], 10)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { VideoRateType } from '../../../../../shared/models/videos/video-rate.ty
|
||||||
import { VideoUpdate } from '../../../../../shared/models/videos/video-update.model'
|
import { VideoUpdate } from '../../../../../shared/models/videos/video-update.model'
|
||||||
import { RestExtractor } from '../rest/rest-extractor.service'
|
import { RestExtractor } from '../rest/rest-extractor.service'
|
||||||
import { RestService } from '../rest/rest.service'
|
import { RestService } from '../rest/rest.service'
|
||||||
import { Search } from '../search/search.model'
|
import { Search } from '../header/search.model'
|
||||||
import { UserService } from '../users/user.service'
|
import { UserService } from '../users/user.service'
|
||||||
import { SortField } from './sort-field.type'
|
import { SortField } from './sort-field.type'
|
||||||
import { VideoDetails } from './video-details.model'
|
import { VideoDetails } from './video-details.model'
|
||||||
|
@ -91,15 +91,14 @@ export class VideoService {
|
||||||
.catch((res) => this.restExtractor.handleError(res))
|
.catch((res) => this.restExtractor.handleError(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
searchVideos (search: Search, videoPagination: VideoPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> {
|
searchVideos (search: string, videoPagination: VideoPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> {
|
||||||
const url = VideoService.BASE_VIDEO_URL + 'search/' + encodeURIComponent(search.value)
|
const url = VideoService.BASE_VIDEO_URL + 'search'
|
||||||
|
|
||||||
const pagination = this.videoPaginationToRestPagination(videoPagination)
|
const pagination = this.videoPaginationToRestPagination(videoPagination)
|
||||||
|
|
||||||
let params = new HttpParams()
|
let params = new HttpParams()
|
||||||
params = this.restService.addRestGetParams(params, pagination, sort)
|
params = this.restService.addRestGetParams(params, pagination, sort)
|
||||||
|
params = params.append('search', search)
|
||||||
if (search.field) params.set('field', search.field)
|
|
||||||
|
|
||||||
return this.authHttp
|
return this.authHttp
|
||||||
.get<ResultList<VideoServerModel>>(url, { params })
|
.get<ResultList<VideoServerModel>>(url, { params })
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="margin-content">
|
<div class="margin-content">
|
||||||
|
|
||||||
<div class="title-page title-page-single">
|
<div class="title-page title-page-single">
|
||||||
Signup
|
Create an account
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './video-recently-added.component'
|
export * from './video-recently-added.component'
|
||||||
export * from './video-trending.component'
|
export * from './video-trending.component'
|
||||||
|
export * from './video-search.component'
|
||||||
export * from './shared'
|
export * from './shared'
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { VideoService } from '../../shared/video/video.service'
|
|
||||||
import { AbstractVideoList } from '../../shared/video/abstract-video-list'
|
import { AbstractVideoList } from '../../shared/video/abstract-video-list'
|
||||||
|
import { SortField } from '../../shared/video/sort-field.type'
|
||||||
|
import { VideoService } from '../../shared/video/video.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-videos-recently-added',
|
selector: 'my-videos-recently-added',
|
||||||
styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
|
styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
|
||||||
templateUrl: '../../shared/video/abstract-video-list.html'
|
templateUrl: '../../shared/video/abstract-video-list.html'
|
||||||
})
|
})
|
||||||
export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy {
|
export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit {
|
||||||
titlePage = 'Recently added'
|
titlePage = 'Recently added'
|
||||||
currentRoute = '/videos/recently-added'
|
currentRoute = '/videos/recently-added'
|
||||||
|
sort: SortField = '-createdAt'
|
||||||
|
|
||||||
constructor (protected router: Router,
|
constructor (protected router: Router,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
|
@ -24,10 +26,6 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
|
||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
|
||||||
super.ngOnDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
getVideosObservable () {
|
getVideosObservable () {
|
||||||
return this.videoService.getVideos(this.pagination, this.sort)
|
return this.videoService.getVideos(this.pagination, this.sort)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
|
import { AbstractVideoList } from 'app/shared/video/abstract-video-list'
|
||||||
|
import { Subscription } from 'rxjs/Subscription'
|
||||||
|
import { SortField } from '../../shared/video/sort-field.type'
|
||||||
|
import { VideoService } from '../../shared/video/video.service'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-videos-search',
|
||||||
|
styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
|
||||||
|
templateUrl: '../../shared/video/abstract-video-list.html'
|
||||||
|
})
|
||||||
|
export class VideoSearchComponent extends AbstractVideoList implements OnInit, OnDestroy {
|
||||||
|
titlePage = 'Search'
|
||||||
|
currentRoute = '/videos/search'
|
||||||
|
loadOnInit = false
|
||||||
|
|
||||||
|
private search = ''
|
||||||
|
private subActivatedRoute: Subscription
|
||||||
|
|
||||||
|
constructor (protected router: Router,
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
protected notificationsService: NotificationsService,
|
||||||
|
private videoService: VideoService) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
super.ngOnInit()
|
||||||
|
|
||||||
|
this.subActivatedRoute = this.route.queryParams.subscribe(
|
||||||
|
queryParams => {
|
||||||
|
this.search = queryParams['search']
|
||||||
|
this.reloadVideos()
|
||||||
|
},
|
||||||
|
|
||||||
|
err => this.notificationsService.error('Error', err.text)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy () {
|
||||||
|
if (this.subActivatedRoute) {
|
||||||
|
this.subActivatedRoute.unsubscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getVideosObservable () {
|
||||||
|
return this.videoService.searchVideos(this.search, this.pagination, this.sort)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,19 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { NotificationsService } from 'angular2-notifications'
|
import { NotificationsService } from 'angular2-notifications'
|
||||||
import { VideoService } from '../../shared/video/video.service'
|
|
||||||
import { AbstractVideoList } from 'app/shared/video/abstract-video-list'
|
import { AbstractVideoList } from 'app/shared/video/abstract-video-list'
|
||||||
|
import { SortField } from '../../shared/video/sort-field.type'
|
||||||
|
import { VideoService } from '../../shared/video/video.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-videos-trending',
|
selector: 'my-videos-trending',
|
||||||
styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
|
styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
|
||||||
templateUrl: '../../shared/video/abstract-video-list.html'
|
templateUrl: '../../shared/video/abstract-video-list.html'
|
||||||
})
|
})
|
||||||
export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy {
|
export class VideoTrendingComponent extends AbstractVideoList implements OnInit {
|
||||||
titlePage = 'Trending'
|
titlePage = 'Trending'
|
||||||
currentRoute = '/videos/trending'
|
currentRoute = '/videos/trending'
|
||||||
|
defaultSort: SortField = '-views'
|
||||||
|
|
||||||
constructor (protected router: Router,
|
constructor (protected router: Router,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
|
@ -24,10 +26,6 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
|
||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
|
||||||
super.ngOnDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
getVideosObservable () {
|
getVideosObservable () {
|
||||||
return this.videoService.getVideos(this.pagination, this.sort)
|
return this.videoService.getVideos(this.pagination, this.sort)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { RouterModule, Routes } from '@angular/router'
|
import { RouterModule, Routes } from '@angular/router'
|
||||||
import { MetaGuard } from '@ngx-meta/core'
|
import { MetaGuard } from '@ngx-meta/core'
|
||||||
|
import { VideoSearchComponent } from './video-list'
|
||||||
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
|
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
|
||||||
import { VideoTrendingComponent } from './video-list/video-trending.component'
|
import { VideoTrendingComponent } from './video-list/video-trending.component'
|
||||||
import { VideosComponent } from './videos.component'
|
import { VideosComponent } from './videos.component'
|
||||||
|
@ -34,6 +35,15 @@ const videosRoutes: Routes = [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'search',
|
||||||
|
component: VideoSearchComponent,
|
||||||
|
data: {
|
||||||
|
meta: {
|
||||||
|
title: 'Search videos'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'upload',
|
path: 'upload',
|
||||||
loadChildren: 'app/videos/+video-edit#VideoAddModule',
|
loadChildren: 'app/videos/+video-edit#VideoAddModule',
|
||||||
|
@ -54,6 +64,7 @@ const videosRoutes: Routes = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':uuid',
|
path: ':uuid',
|
||||||
|
pathMatch: 'full',
|
||||||
redirectTo: 'watch/:uuid'
|
redirectTo: 'watch/:uuid'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { SharedModule } from '../shared'
|
import { SharedModule } from '../shared'
|
||||||
import { VideoMiniatureComponent } from './video-list'
|
import { VideoMiniatureComponent, VideoSearchComponent } from './video-list'
|
||||||
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
|
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
|
||||||
import { VideoTrendingComponent } from './video-list/video-trending.component'
|
import { VideoTrendingComponent } from './video-list/video-trending.component'
|
||||||
import { VideosRoutingModule } from './videos-routing.module'
|
import { VideosRoutingModule } from './videos-routing.module'
|
||||||
|
@ -17,7 +17,8 @@ import { VideosComponent } from './videos.component'
|
||||||
|
|
||||||
VideoTrendingComponent,
|
VideoTrendingComponent,
|
||||||
VideoRecentlyAddedComponent,
|
VideoRecentlyAddedComponent,
|
||||||
VideoMiniatureComponent
|
VideoMiniatureComponent,
|
||||||
|
VideoSearchComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
exports: [
|
exports: [
|
||||||
|
|
|
@ -26,7 +26,6 @@ import {
|
||||||
authenticate,
|
authenticate,
|
||||||
paginationValidator,
|
paginationValidator,
|
||||||
setPagination,
|
setPagination,
|
||||||
setVideosSearch,
|
|
||||||
setVideosSort,
|
setVideosSort,
|
||||||
videosAddValidator,
|
videosAddValidator,
|
||||||
videosGetValidator,
|
videosGetValidator,
|
||||||
|
@ -84,6 +83,14 @@ videosRouter.get('/',
|
||||||
setPagination,
|
setPagination,
|
||||||
asyncMiddleware(listVideos)
|
asyncMiddleware(listVideos)
|
||||||
)
|
)
|
||||||
|
videosRouter.get('/search',
|
||||||
|
videosSearchValidator,
|
||||||
|
paginationValidator,
|
||||||
|
videosSortValidator,
|
||||||
|
setVideosSort,
|
||||||
|
setPagination,
|
||||||
|
asyncMiddleware(searchVideos)
|
||||||
|
)
|
||||||
videosRouter.put('/:id',
|
videosRouter.put('/:id',
|
||||||
authenticate,
|
authenticate,
|
||||||
asyncMiddleware(videosUpdateValidator),
|
asyncMiddleware(videosUpdateValidator),
|
||||||
|
@ -115,16 +122,6 @@ videosRouter.delete('/:id',
|
||||||
asyncMiddleware(removeVideoRetryWrapper)
|
asyncMiddleware(removeVideoRetryWrapper)
|
||||||
)
|
)
|
||||||
|
|
||||||
videosRouter.get('/search/:value',
|
|
||||||
videosSearchValidator,
|
|
||||||
paginationValidator,
|
|
||||||
videosSortValidator,
|
|
||||||
setVideosSort,
|
|
||||||
setPagination,
|
|
||||||
setVideosSearch,
|
|
||||||
asyncMiddleware(searchVideos)
|
|
||||||
)
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -378,8 +375,7 @@ async function removeVideo (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
|
const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
|
||||||
req.params.value,
|
req.query.search,
|
||||||
req.query.field,
|
|
||||||
req.query.start,
|
req.query.start,
|
||||||
req.query.count,
|
req.query.count,
|
||||||
req.query.sort
|
req.query.sort
|
||||||
|
|
|
@ -24,11 +24,6 @@ const API_VERSION = 'v1'
|
||||||
// Number of results by default for the pagination
|
// Number of results by default for the pagination
|
||||||
const PAGINATION_COUNT_DEFAULT = 15
|
const PAGINATION_COUNT_DEFAULT = 15
|
||||||
|
|
||||||
// Sortable columns per schema
|
|
||||||
const SEARCHABLE_COLUMNS = {
|
|
||||||
VIDEOS: [ 'name', 'magnetUri', 'host', 'account', 'tags' ]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sortable columns per schema
|
// Sortable columns per schema
|
||||||
const SORTABLE_COLUMNS = {
|
const SORTABLE_COLUMNS = {
|
||||||
USERS: [ 'id', 'username', 'createdAt' ],
|
USERS: [ 'id', 'username', 'createdAt' ],
|
||||||
|
@ -361,7 +356,6 @@ export {
|
||||||
REMOTE_SCHEME,
|
REMOTE_SCHEME,
|
||||||
FOLLOW_STATES,
|
FOLLOW_STATES,
|
||||||
AVATARS_DIR,
|
AVATARS_DIR,
|
||||||
SEARCHABLE_COLUMNS,
|
|
||||||
SERVER_ACCOUNT_NAME,
|
SERVER_ACCOUNT_NAME,
|
||||||
PRIVATE_RSA_KEY_SIZE,
|
PRIVATE_RSA_KEY_SIZE,
|
||||||
SORTABLE_COLUMNS,
|
SORTABLE_COLUMNS,
|
||||||
|
|
|
@ -4,6 +4,5 @@ export * from './async'
|
||||||
export * from './oauth'
|
export * from './oauth'
|
||||||
export * from './pagination'
|
export * from './pagination'
|
||||||
export * from './servers'
|
export * from './servers'
|
||||||
export * from './search'
|
|
||||||
export * from './sort'
|
export * from './sort'
|
||||||
export * from './user-right'
|
export * from './user-right'
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import 'express-validator'
|
|
||||||
import * as express from 'express'
|
|
||||||
|
|
||||||
function setVideosSearch (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
if (!req.query.field) req.query.field = 'name'
|
|
||||||
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export {
|
|
||||||
setVideosSearch
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
} from '../../helpers/custom-validators/videos'
|
} from '../../helpers/custom-validators/videos'
|
||||||
import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils'
|
import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils'
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
||||||
import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
|
import { CONSTRAINTS_FIELDS } from '../../initializers'
|
||||||
import { database as db } from '../../initializers/database'
|
import { database as db } from '../../initializers/database'
|
||||||
import { UserInstance } from '../../models/account/user-interface'
|
import { UserInstance } from '../../models/account/user-interface'
|
||||||
import { VideoInstance } from '../../models/video/video-interface'
|
import { VideoInstance } from '../../models/video/video-interface'
|
||||||
|
@ -172,8 +172,7 @@ const videosRemoveValidator = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const videosSearchValidator = [
|
const videosSearchValidator = [
|
||||||
param('value').not().isEmpty().withMessage('Should have a valid search'),
|
query('search').not().isEmpty().withMessage('Should have a valid search'),
|
||||||
query('field').optional().isIn(SEARCHABLE_COLUMNS.VIDEOS).withMessage('Should have correct searchable column'),
|
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking videosSearch parameters', { parameters: req.params })
|
logger.debug('Checking videosSearch parameters', { parameters: req.params })
|
||||||
|
|
|
@ -50,7 +50,6 @@ export namespace VideoMethods {
|
||||||
export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
|
||||||
export type SearchAndPopulateAccountAndServerAndTags = (
|
export type SearchAndPopulateAccountAndServerAndTags = (
|
||||||
value: string,
|
value: string,
|
||||||
field: string,
|
|
||||||
start: number,
|
start: number,
|
||||||
count: number,
|
count: number,
|
||||||
sort: string
|
sort: string
|
||||||
|
|
|
@ -1070,7 +1070,7 @@ loadByUUIDAndPopulateAccountAndServerAndTags = function (uuid: string) {
|
||||||
return Video.findOne(options)
|
return Video.findOne(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAndPopulateAccountAndServerAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
|
searchAndPopulateAccountAndServerAndTags = function (value: string, start: number, count: number, sort: string) {
|
||||||
const serverInclude: Sequelize.IncludeOptions = {
|
const serverInclude: Sequelize.IncludeOptions = {
|
||||||
model: Video['sequelize'].models.Server,
|
model: Video['sequelize'].models.Server,
|
||||||
required: false
|
required: false
|
||||||
|
@ -1099,33 +1099,24 @@ searchAndPopulateAccountAndServerAndTags = function (value: string, field: strin
|
||||||
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
|
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field === 'tags') {
|
// TODO: search on tags too
|
||||||
const escapedValue = Video['sequelize'].escape('%' + value + '%')
|
// const escapedValue = Video['sequelize'].escape('%' + value + '%')
|
||||||
query.where['id'][Sequelize.Op.in] = Video['sequelize'].literal(
|
// query.where['id'][Sequelize.Op.in] = Video['sequelize'].literal(
|
||||||
`(SELECT "VideoTags"."videoId"
|
// `(SELECT "VideoTags"."videoId"
|
||||||
FROM "Tags"
|
// FROM "Tags"
|
||||||
INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId"
|
// INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId"
|
||||||
WHERE name ILIKE ${escapedValue}
|
// WHERE name ILIKE ${escapedValue}
|
||||||
)`
|
// )`
|
||||||
)
|
// )
|
||||||
} else if (field === 'host') {
|
|
||||||
// FIXME: Include our server? (not stored in the database)
|
// TODO: search on account too
|
||||||
serverInclude.where = {
|
// accountInclude.where = {
|
||||||
host: {
|
// name: {
|
||||||
[Sequelize.Op.iLike]: '%' + value + '%'
|
// [Sequelize.Op.iLike]: '%' + value + '%'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
serverInclude.required = true
|
query.where['name'] = {
|
||||||
} else if (field === 'account') {
|
[Sequelize.Op.iLike]: '%' + value + '%'
|
||||||
accountInclude.where = {
|
|
||||||
name: {
|
|
||||||
[Sequelize.Op.iLike]: '%' + value + '%'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
query.where[field] = {
|
|
||||||
[Sequelize.Op.iLike]: '%' + value + '%'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
query.include = [
|
query.include = [
|
||||||
|
|
|
@ -225,7 +225,7 @@ describe('Test a single server', function () {
|
||||||
expect(video.views).to.equal(3)
|
expect(video.views).to.equal(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search the video by name by default', async function () {
|
it('Should search the video by name', async function () {
|
||||||
const res = await searchVideo(server.url, 'my')
|
const res = await searchVideo(server.url, 'my')
|
||||||
|
|
||||||
expect(res.body.total).to.equal(1)
|
expect(res.body.total).to.equal(1)
|
||||||
|
@ -279,35 +279,36 @@ describe('Test a single server', function () {
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
|
|
||||||
it('Should search the video by tag', async function () {
|
// Not implemented yet
|
||||||
const res = await searchVideo(server.url, 'tag1', 'tags')
|
// it('Should search the video by tag', async function () {
|
||||||
|
// const res = await searchVideo(server.url, 'tag1')
|
||||||
|
//
|
||||||
|
// expect(res.body.total).to.equal(1)
|
||||||
|
// expect(res.body.data).to.be.an('array')
|
||||||
|
// expect(res.body.data.length).to.equal(1)
|
||||||
|
//
|
||||||
|
// const video = res.body.data[0]
|
||||||
|
// expect(video.name).to.equal('my super name')
|
||||||
|
// expect(video.category).to.equal(2)
|
||||||
|
// expect(video.categoryLabel).to.equal('Films')
|
||||||
|
// expect(video.licence).to.equal(6)
|
||||||
|
// expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives')
|
||||||
|
// expect(video.language).to.equal(3)
|
||||||
|
// expect(video.languageLabel).to.equal('Mandarin')
|
||||||
|
// expect(video.nsfw).to.be.ok
|
||||||
|
// expect(video.description).to.equal('my super description')
|
||||||
|
// expect(video.serverHost).to.equal('localhost:9001')
|
||||||
|
// expect(video.account).to.equal('root')
|
||||||
|
// expect(video.isLocal).to.be.true
|
||||||
|
// expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ])
|
||||||
|
// expect(dateIsValid(video.createdAt)).to.be.true
|
||||||
|
// expect(dateIsValid(video.updatedAt)).to.be.true
|
||||||
|
//
|
||||||
|
// const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
|
||||||
|
// expect(test).to.equal(true)
|
||||||
|
// })
|
||||||
|
|
||||||
expect(res.body.total).to.equal(1)
|
it('Should not find a search by name', async function () {
|
||||||
expect(res.body.data).to.be.an('array')
|
|
||||||
expect(res.body.data.length).to.equal(1)
|
|
||||||
|
|
||||||
const video = res.body.data[0]
|
|
||||||
expect(video.name).to.equal('my super name')
|
|
||||||
expect(video.category).to.equal(2)
|
|
||||||
expect(video.categoryLabel).to.equal('Films')
|
|
||||||
expect(video.licence).to.equal(6)
|
|
||||||
expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives')
|
|
||||||
expect(video.language).to.equal(3)
|
|
||||||
expect(video.languageLabel).to.equal('Mandarin')
|
|
||||||
expect(video.nsfw).to.be.ok
|
|
||||||
expect(video.description).to.equal('my super description')
|
|
||||||
expect(video.serverHost).to.equal('localhost:9001')
|
|
||||||
expect(video.account).to.equal('root')
|
|
||||||
expect(video.isLocal).to.be.true
|
|
||||||
expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ])
|
|
||||||
expect(dateIsValid(video.createdAt)).to.be.true
|
|
||||||
expect(dateIsValid(video.updatedAt)).to.be.true
|
|
||||||
|
|
||||||
const test = await testVideoImage(server.url, 'video_short.webm', video.thumbnailPath)
|
|
||||||
expect(test).to.equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should not find a search by name by default', async function () {
|
|
||||||
const res = await searchVideo(server.url, 'hello')
|
const res = await searchVideo(server.url, 'hello')
|
||||||
|
|
||||||
expect(res.body.total).to.equal(0)
|
expect(res.body.total).to.equal(0)
|
||||||
|
@ -315,21 +316,23 @@ describe('Test a single server', function () {
|
||||||
expect(res.body.data.length).to.equal(0)
|
expect(res.body.data.length).to.equal(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not find a search by author', async function () {
|
// Not implemented yet
|
||||||
const res = await searchVideo(server.url, 'hello', 'account')
|
// it('Should not find a search by author', async function () {
|
||||||
|
// const res = await searchVideo(server.url, 'hello')
|
||||||
expect(res.body.total).to.equal(0)
|
//
|
||||||
expect(res.body.data).to.be.an('array')
|
// expect(res.body.total).to.equal(0)
|
||||||
expect(res.body.data.length).to.equal(0)
|
// expect(res.body.data).to.be.an('array')
|
||||||
})
|
// expect(res.body.data.length).to.equal(0)
|
||||||
|
// })
|
||||||
it('Should not find a search by tag', async function () {
|
//
|
||||||
const res = await searchVideo(server.url, 'hello', 'tags')
|
// Not implemented yet
|
||||||
|
// it('Should not find a search by tag', async function () {
|
||||||
expect(res.body.total).to.equal(0)
|
// const res = await searchVideo(server.url, 'hello')
|
||||||
expect(res.body.data).to.be.an('array')
|
//
|
||||||
expect(res.body.data.length).to.equal(0)
|
// expect(res.body.total).to.equal(0)
|
||||||
})
|
// expect(res.body.data).to.be.an('array')
|
||||||
|
// expect(res.body.data.length).to.equal(0)
|
||||||
|
// })
|
||||||
|
|
||||||
it('Should remove the video', async function () {
|
it('Should remove the video', async function () {
|
||||||
await removeVideo(server.url, server.accessToken, videoId)
|
await removeVideo(server.url, server.accessToken, videoId)
|
||||||
|
@ -443,7 +446,7 @@ describe('Test a single server', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search the first video', async function () {
|
it('Should search the first video', async function () {
|
||||||
const res = await searchVideoWithPagination(server.url, 'webm', 'name', 0, 1, 'name')
|
const res = await searchVideoWithPagination(server.url, 'webm', 0, 1, 'name')
|
||||||
|
|
||||||
const videos = res.body.data
|
const videos = res.body.data
|
||||||
expect(res.body.total).to.equal(4)
|
expect(res.body.total).to.equal(4)
|
||||||
|
@ -452,7 +455,7 @@ describe('Test a single server', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search the last two videos', async function () {
|
it('Should search the last two videos', async function () {
|
||||||
const res = await searchVideoWithPagination(server.url, 'webm', 'name', 2, 2, 'name')
|
const res = await searchVideoWithPagination(server.url, 'webm', 2, 2, 'name')
|
||||||
|
|
||||||
const videos = res.body.data
|
const videos = res.body.data
|
||||||
expect(res.body.total).to.equal(4)
|
expect(res.body.total).to.equal(4)
|
||||||
|
@ -462,20 +465,21 @@ describe('Test a single server', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search all the webm videos', async function () {
|
it('Should search all the webm videos', async function () {
|
||||||
const res = await searchVideoWithPagination(server.url, 'webm', 'name', 0, 15)
|
const res = await searchVideoWithPagination(server.url, 'webm', 0, 15)
|
||||||
|
|
||||||
const videos = res.body.data
|
const videos = res.body.data
|
||||||
expect(res.body.total).to.equal(4)
|
expect(res.body.total).to.equal(4)
|
||||||
expect(videos.length).to.equal(4)
|
expect(videos.length).to.equal(4)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should search all the root author videos', async function () {
|
// Not implemented yet
|
||||||
const res = await searchVideoWithPagination(server.url, 'root', 'account', 0, 15)
|
// it('Should search all the root author videos', async function () {
|
||||||
|
// const res = await searchVideoWithPagination(server.url, 'root', 0, 15)
|
||||||
const videos = res.body.data
|
//
|
||||||
expect(res.body.total).to.equal(6)
|
// const videos = res.body.data
|
||||||
expect(videos.length).to.equal(6)
|
// expect(res.body.total).to.equal(6)
|
||||||
})
|
// expect(videos.length).to.equal(6)
|
||||||
|
// })
|
||||||
|
|
||||||
// Not implemented yet
|
// Not implemented yet
|
||||||
// it('Should search all the 9001 port videos', async function () {
|
// it('Should search all the 9001 port videos', async function () {
|
||||||
|
|
|
@ -145,26 +145,25 @@ function removeVideo (url: string, token: string, id: number, expectedStatus = 2
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchVideo (url: string, search: string, field?: string) {
|
function searchVideo (url: string, search: string) {
|
||||||
const path = '/api/v1/videos'
|
const path = '/api/v1/videos'
|
||||||
const req = request(url)
|
const req = request(url)
|
||||||
.get(path + '/search/' + search)
|
.get(path + '/search')
|
||||||
.set('Accept', 'application/json')
|
.query({ search })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
if (field) req.query({ field })
|
|
||||||
|
|
||||||
return req.expect(200)
|
return req.expect(200)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchVideoWithPagination (url: string, search: string, field: string, start: number, count: number, sort?: string) {
|
function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
|
||||||
const path = '/api/v1/videos'
|
const path = '/api/v1/videos'
|
||||||
|
|
||||||
const req = request(url)
|
const req = request(url)
|
||||||
.get(path + '/search/' + search)
|
.get(path + '/search')
|
||||||
.query({ start })
|
.query({ start })
|
||||||
|
.query({ search })
|
||||||
.query({ count })
|
.query({ count })
|
||||||
.query({ field })
|
|
||||||
|
|
||||||
if (sort) req.query({ sort })
|
if (sort) req.query({ sort })
|
||||||
|
|
||||||
|
@ -177,7 +176,8 @@ function searchVideoWithSort (url: string, search: string, sort: string) {
|
||||||
const path = '/api/v1/videos'
|
const path = '/api/v1/videos'
|
||||||
|
|
||||||
return request(url)
|
return request(url)
|
||||||
.get(path + '/search/' + search)
|
.get(path + '/search')
|
||||||
|
.query({ search })
|
||||||
.query({ sort })
|
.query({ sort })
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
Loading…
Reference in New Issue