From d0f58214dfd3fea6afdfa6e500ed496a71f23642 Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Tue, 12 Jan 2021 15:23:57 +0100 Subject: [PATCH] add search to account view --- .../account-search.component.ts | 19 +++++++++++--- .../src/app/+accounts/accounts.component.html | 2 +- .../src/app/+accounts/accounts.component.ts | 8 +++--- .../misc/simple-search-input.component.html | 25 ++++++++++--------- .../misc/simple-search-input.component.scss | 13 +++++++--- .../misc/simple-search-input.component.ts | 22 +++++++--------- .../shared/shared-main/video/video.service.ts | 7 +++++- server/controllers/api/accounts.ts | 3 ++- .../middlewares/validators/videos/videos.ts | 4 +++ 9 files changed, 65 insertions(+), 38 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 index 6db4e7636172..10c7a12d87da 100644 --- a/client/src/app/+accounts/account-search/account-search.component.ts +++ b/client/src/app/+accounts/account-search/account-search.component.ts @@ -19,6 +19,7 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit, titlePage: string loadOnInit = false + search = '' filter: VideoFilter = null private account: Account @@ -62,6 +63,13 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit, super.ngOnDestroy() } + updateSearch (value: string) { + if (value === '') this.router.navigate(['../videos'], { relativeTo: this.route }) + this.search = value + + this.reloadVideos() + } + getVideosObservable (page: number) { const newPagination = immutableAssign(this.pagination, { currentPage: page }) const options = { @@ -69,14 +77,17 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit, videoPagination: newPagination, sort: this.sort, nsfwPolicy: this.nsfwPolicy, - videoFilter: this.filter + videoFilter: this.filter, + search: this.search } return this.videoService .getAccountVideos(options) .pipe( tap(({ total }) => { - this.titlePage = $localize`${total} results on this account for TODO` + this.titlePage = this.search + ? $localize`Published ${total} videos matching "${this.search}"` + : $localize`Published ${total} videos` }) ) } @@ -87,5 +98,7 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit, this.reloadVideos() } - generateSyndicationList () {} + generateSyndicationList () { + /* disable syndication */ + } } diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html index 15170f821a6a..5bd7b0824d6a 100644 --- a/client/src/app/+accounts/accounts.component.html +++ b/client/src/app/+accounts/accounts.component.html @@ -45,7 +45,7 @@ - + diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts index 840537013f97..1458ea59c40a 100644 --- a/client/src/app/+accounts/accounts.component.ts +++ b/client/src/app/+accounts/accounts.component.ts @@ -15,6 +15,7 @@ import { AccountSearchComponent } from './account-search/account-search.componen }) export class AccountsComponent implements OnInit, OnDestroy { @ViewChild('accountReportModal') accountReportModal: AccountReportComponent + accountSearch: AccountSearchComponent account: Account accountUser: User @@ -102,13 +103,14 @@ export class AccountsComponent implements OnInit, OnDestroy { onOutletLoaded (component: Component) { if (component instanceof AccountSearchComponent) { - console.log('AccounSearchComponent') + this.accountSearch = component + } else { + this.accountSearch = undefined } - console.log('not AccountSearchComponent') } searchChanged (search: string) { - console.log('search: ' + search) + if (this.accountSearch) this.accountSearch.updateSearch(search) } private onAccount (account: Account) { diff --git a/client/src/app/shared/shared-main/misc/simple-search-input.component.html b/client/src/app/shared/shared-main/misc/simple-search-input.component.html index bdcd0dae7f1d..fb0d97122cf7 100644 --- a/client/src/app/shared/shared-main/misc/simple-search-input.component.html +++ b/client/src/app/shared/shared-main/misc/simple-search-input.component.html @@ -1,13 +1,14 @@ - + + - + + diff --git a/client/src/app/shared/shared-main/misc/simple-search-input.component.scss b/client/src/app/shared/shared-main/misc/simple-search-input.component.scss index 1565158adf07..591b04fb2f60 100644 --- a/client/src/app/shared/shared-main/misc/simple-search-input.component.scss +++ b/client/src/app/shared/shared-main/misc/simple-search-input.component.scss @@ -1,19 +1,24 @@ @import '_variables'; @import '_mixins'; +span { + opacity: .6; + + &:focus-within { + opacity: 1; + } +} + my-global-icon { height: 18px; position: relative; top: -2px; - - opacity: .6; - color: pvar(--mainForegroundColor); } input { @include peertube-input-text(150px); - height: 24px; // maximum height for the account/video-channels links + height: 22px; // maximum height for the account/video-channels links padding-left: 10px; background-color: transparent; border: none; diff --git a/client/src/app/shared/shared-main/misc/simple-search-input.component.ts b/client/src/app/shared/shared-main/misc/simple-search-input.component.ts index 1ea94bce2cd9..86ae9ab4222c 100644 --- a/client/src/app/shared/shared-main/misc/simple-search-input.component.ts +++ b/client/src/app/shared/shared-main/misc/simple-search-input.component.ts @@ -9,16 +9,17 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators' styleUrls: [ './simple-search-input.component.scss' ] }) export class SimpleSearchInputComponent implements OnInit { - @ViewChild("searchVideos") input: ElementRef + @ViewChild('ref') input: ElementRef - @Input() enter: string + @Input() name = 'search' + @Input() placeholder = $localize`Search` @Output() searchChanged = new EventEmitter() - search = '' + value = '' shown: boolean - private searchSubject= new Subject() + private searchSubject = new Subject() constructor ( private router: Router, @@ -33,26 +34,21 @@ export class SimpleSearchInputComponent implements OnInit { ) .subscribe(value => this.searchChanged.emit(value)) - this.searchSubject.next(this.search) + this.searchSubject.next(this.value) } showInput () { this.shown = true - setTimeout(()=> { - this.input.nativeElement.focus() - }) + setTimeout(() => this.input.nativeElement.focus()) } focusLost () { - if (this.search !== '') return + if (this.value !== '') return this.shown = false } searchChange () { - this.searchChanged.emit(this.search) - } - - navigate () { this.router.navigate(['./search'], { relativeTo: this.route }) + this.searchSubject.next(this.value) } } diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts index 59860c5cb75f..0b708b692c35 100644 --- a/client/src/app/shared/shared-main/video/video.service.ts +++ b/client/src/app/shared/shared-main/video/video.service.ts @@ -140,8 +140,9 @@ export class VideoService implements VideosProvider { sort: VideoSortField nsfwPolicy?: NSFWPolicyType videoFilter?: VideoFilter + search?: string }): Observable> { - const { account, videoPagination, sort, videoFilter, nsfwPolicy } = parameters + const { account, videoPagination, sort, videoFilter, nsfwPolicy, search } = parameters const pagination = this.restService.componentPaginationToRestPagination(videoPagination) @@ -156,6 +157,10 @@ export class VideoService implements VideosProvider { params = params.set('filter', videoFilter) } + if (search) { + params = params.set('search', search) + } + return this.authHttp .get>(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params }) .pipe( diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index e807b4f446ea..e31924a9410b 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts @@ -175,7 +175,8 @@ async function listAccountVideos (req: express.Request, res: express.Response) { withFiles: false, accountId: account.id, user: res.locals.oauth ? res.locals.oauth.token.User : undefined, - countVideos + countVideos, + search: req.query.search }, 'filter:api.accounts.videos.list.params') const resultList = await Hooks.wrapPromiseFun( diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 8bc37b0abd84..84e309bece2b 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts @@ -6,6 +6,7 @@ import { MVideoFullLight } from '@server/types/models' import { ServerErrorCode, UserRight, VideoChangeOwnershipStatus, VideoPrivacy } from '../../../../shared' import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model' import { + exists, isBooleanValid, isDateValid, isFileFieldValid, @@ -444,6 +445,9 @@ const commonVideosFiltersValidator = [ .optional() .customSanitizer(toBooleanOrNull) .custom(isBooleanValid).withMessage('Should have a valid skip count boolean'), + query('search') + .optional() + .custom(exists).withMessage('Should have a valid search'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking commons video filters query', { parameters: req.query })