Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users/visitors to search through an account's videos #3589

Merged
merged 3 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add search to account view
  • Loading branch information
rigelk committed Jan 18, 2021
commit 74a64a6b119ac50c5988e5a894827bb2af2d9b55
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit,
titlePage: string
loadOnInit = false

search = ''
filter: VideoFilter = null

private account: Account
Expand Down Expand Up @@ -62,21 +63,31 @@ 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 = {
account: this.account,
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`
})
)
}
Expand All @@ -87,5 +98,7 @@ export class AccountSearchComponent extends AbstractVideoList implements OnInit,
this.reloadVideos()
}

generateSyndicationList () {}
generateSyndicationList () {
/* disable syndication */
}
}
2 changes: 1 addition & 1 deletion client/src/app/+accounts/accounts.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

<list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow>

<simple-search-input (searchChanged)="searchChanged($event)" (enter)="'search'"></simple-search-input>
<simple-search-input (searchChanged)="searchChanged($event)" name="search-videos" i18n-placeholder placeholder="Search videos"></simple-search-input>
</div>
</div>

Expand Down
8 changes: 5 additions & 3 deletions client/src/app/+accounts/accounts.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<my-global-icon iconName="search" aria-label="Search" role="button" (click)="showInput()"></my-global-icon>
<span>
<my-global-icon iconName="search" aria-label="Search" role="button" (click)="showInput()"></my-global-icon>

<input
#searchVideos
name="search-videos"
type="text"
[(ngModel)]="search"
(ngModelChange)="searchChange"
i18n-placeholder placeholder="Search videos"
(focusout)="focusLost()"
(keyup.enter)="navigate()"
[hidden]="!shown"
>
<input
#ref
type="text"
[(ngModel)]="value"
(focusout)="focusLost()"
(keyup.enter)="searchChange()"
[hidden]="!shown"
[name]="name"
[placeholder]="placeholder"
>
</span>
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>()

search = ''
value = ''
shown: boolean

private searchSubject= new Subject<string>()
private searchSubject = new Subject<string>()

constructor (
private router: Router,
Expand All @@ -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)
}
}
7 changes: 6 additions & 1 deletion client/src/app/shared/shared-main/video/video.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ export class VideoService implements VideosProvider {
sort: VideoSortField
nsfwPolicy?: NSFWPolicyType
videoFilter?: VideoFilter
search?: string
}): Observable<ResultList<Video>> {
const { account, videoPagination, sort, videoFilter, nsfwPolicy } = parameters
const { account, videoPagination, sort, videoFilter, nsfwPolicy, search } = parameters

const pagination = this.restService.componentPaginationToRestPagination(videoPagination)

Expand All @@ -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<ResultList<Video>>(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params })
.pipe(
Expand Down
3 changes: 2 additions & 1 deletion server/controllers/api/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions server/middlewares/validators/videos/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 })
Expand Down