diff options
author | Chocobozzz <me@florianbigard.com> | 2021-07-29 15:19:22 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-07-29 15:19:22 +0200 |
commit | af7fd04a6706fb781e4622167b08dc6c9376f06a (patch) | |
tree | 4d6a84cd67143e07d762ba967f9d29e947e7436c /client/src/app/+search | |
parent | 9c9a236b541a286e165d67341e4ddd6ea2fabdf1 (diff) | |
download | PeerTube-af7fd04a6706fb781e4622167b08dc6c9376f06a.tar.gz PeerTube-af7fd04a6706fb781e4622167b08dc6c9376f06a.tar.zst PeerTube-af7fd04a6706fb781e4622167b08dc6c9376f06a.zip |
Add ability to filter by host in search page
Diffstat (limited to 'client/src/app/+search')
-rw-r--r-- | client/src/app/+search/search-filters.component.html | 16 | ||||
-rw-r--r-- | client/src/app/+search/search-filters.component.ts | 8 | ||||
-rw-r--r-- | client/src/app/+search/search.component.html | 2 | ||||
-rw-r--r-- | client/src/app/+search/search.component.scss | 4 | ||||
-rw-r--r-- | client/src/app/+search/search.component.ts | 24 |
5 files changed, 42 insertions, 12 deletions
diff --git a/client/src/app/+search/search-filters.component.html b/client/src/app/+search/search-filters.component.html index 421bc7f6f..4b87a2102 100644 --- a/client/src/app/+search/search-filters.component.html +++ b/client/src/app/+search/search-filters.component.html | |||
@@ -63,7 +63,7 @@ | |||
63 | </div> | 63 | </div> |
64 | 64 | ||
65 | <div class="peertube-radio-container" *ngFor="let date of publishedDateRanges"> | 65 | <div class="peertube-radio-container" *ngFor="let date of publishedDateRanges"> |
66 | <input type="radio" (change)="onInputUpdated()" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange"> | 66 | <input type="radio" (change)="onDurationOrPublishedUpdated()" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange"> |
67 | <label [for]="date.id" class="radio">{{ date.label }}</label> | 67 | <label [for]="date.id" class="radio">{{ date.label }}</label> |
68 | </div> | 68 | </div> |
69 | </div> | 69 | </div> |
@@ -79,7 +79,7 @@ | |||
79 | <div class="row"> | 79 | <div class="row"> |
80 | <div class="pl-0 col-sm-6"> | 80 | <div class="pl-0 col-sm-6"> |
81 | <input | 81 | <input |
82 | (change)="onInputUpdated()" | 82 | (change)="onDurationOrPublishedUpdated()" |
83 | (keydown.enter)="$event.preventDefault()" | 83 | (keydown.enter)="$event.preventDefault()" |
84 | type="text" id="original-publication-after" name="original-publication-after" | 84 | type="text" id="original-publication-after" name="original-publication-after" |
85 | i18n-placeholder placeholder="After..." | 85 | i18n-placeholder placeholder="After..." |
@@ -89,7 +89,7 @@ | |||
89 | </div> | 89 | </div> |
90 | <div class="pr-0 col-sm-6"> | 90 | <div class="pr-0 col-sm-6"> |
91 | <input | 91 | <input |
92 | (change)="onInputUpdated()" | 92 | (change)="onDurationOrPublishedUpdated()" |
93 | (keydown.enter)="$event.preventDefault()" | 93 | (keydown.enter)="$event.preventDefault()" |
94 | type="text" id="original-publication-before" name="original-publication-before" | 94 | type="text" id="original-publication-before" name="original-publication-before" |
95 | i18n-placeholder placeholder="Before..." | 95 | i18n-placeholder placeholder="Before..." |
@@ -112,7 +112,7 @@ | |||
112 | </div> | 112 | </div> |
113 | 113 | ||
114 | <div class="peertube-radio-container" *ngFor="let duration of durationRanges"> | 114 | <div class="peertube-radio-container" *ngFor="let duration of durationRanges"> |
115 | <input type="radio" (change)="onInputUpdated()" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange"> | 115 | <input type="radio" (change)="onDurationOrPublishedUpdated()" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange"> |
116 | <label [for]="duration.id" class="radio">{{ duration.label }}</label> | 116 | <label [for]="duration.id" class="radio">{{ duration.label }}</label> |
117 | </div> | 117 | </div> |
118 | </div> | 118 | </div> |
@@ -174,6 +174,14 @@ | |||
174 | <my-select-tags name="tagsOneOf" labelForId="tagsOneOf" id="tagsOneOf" [(ngModel)]="advancedSearch.tagsOneOf"></my-select-tags> | 174 | <my-select-tags name="tagsOneOf" labelForId="tagsOneOf" id="tagsOneOf" [(ngModel)]="advancedSearch.tagsOneOf"></my-select-tags> |
175 | </div> | 175 | </div> |
176 | 176 | ||
177 | <div class="form-group"> | ||
178 | <label i18n for="host">PeerTube instance host</label> | ||
179 | |||
180 | <input (change)="onDurationOrPublishedUpdated()" (keydown.enter)="$event.preventDefault()" type="text" id="host" name="host" | ||
181 | placeholder="example.com" [(ngModel)]="advancedSearch.host" class="form-control" | ||
182 | > | ||
183 | </div> | ||
184 | |||
177 | <div class="form-group" *ngIf="isSearchTargetEnabled()"> | 185 | <div class="form-group" *ngIf="isSearchTargetEnabled()"> |
178 | <div class="radio-label label-container"> | 186 | <div class="radio-label label-container"> |
179 | <label i18n>Search target</label> | 187 | <label i18n>Search target</label> |
diff --git a/client/src/app/+search/search-filters.component.ts b/client/src/app/+search/search-filters.component.ts index afa523b91..5972ba553 100644 --- a/client/src/app/+search/search-filters.component.ts +++ b/client/src/app/+search/search-filters.component.ts | |||
@@ -108,14 +108,14 @@ export class SearchFiltersComponent implements OnInit { | |||
108 | this.loadOriginallyPublishedAtYears() | 108 | this.loadOriginallyPublishedAtYears() |
109 | } | 109 | } |
110 | 110 | ||
111 | onInputUpdated () { | 111 | onDurationOrPublishedUpdated () { |
112 | this.updateModelFromDurationRange() | 112 | this.updateModelFromDurationRange() |
113 | this.updateModelFromPublishedRange() | 113 | this.updateModelFromPublishedRange() |
114 | this.updateModelFromOriginallyPublishedAtYears() | 114 | this.updateModelFromOriginallyPublishedAtYears() |
115 | } | 115 | } |
116 | 116 | ||
117 | formUpdated () { | 117 | formUpdated () { |
118 | this.onInputUpdated() | 118 | this.onDurationOrPublishedUpdated() |
119 | this.filtered.emit(this.advancedSearch) | 119 | this.filtered.emit(this.advancedSearch) |
120 | } | 120 | } |
121 | 121 | ||
@@ -127,7 +127,7 @@ export class SearchFiltersComponent implements OnInit { | |||
127 | this.durationRange = undefined | 127 | this.durationRange = undefined |
128 | this.publishedDateRange = undefined | 128 | this.publishedDateRange = undefined |
129 | 129 | ||
130 | this.onInputUpdated() | 130 | this.onDurationOrPublishedUpdated() |
131 | } | 131 | } |
132 | 132 | ||
133 | resetField (fieldName: string, value?: any) { | 133 | resetField (fieldName: string, value?: any) { |
@@ -136,7 +136,7 @@ export class SearchFiltersComponent implements OnInit { | |||
136 | 136 | ||
137 | resetLocalField (fieldName: string, value?: any) { | 137 | resetLocalField (fieldName: string, value?: any) { |
138 | this[fieldName] = value | 138 | this[fieldName] = value |
139 | this.onInputUpdated() | 139 | this.onDurationOrPublishedUpdated() |
140 | } | 140 | } |
141 | 141 | ||
142 | resetOriginalPublicationYears () { | 142 | resetOriginalPublicationYears () { |
diff --git a/client/src/app/+search/search.component.html b/client/src/app/+search/search.component.html index b28abca6a..dc8b4d595 100644 --- a/client/src/app/+search/search.component.html +++ b/client/src/app/+search/search.component.html | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | <div class="results-filter collapse-transition" [ngbCollapse]="isSearchFilterCollapsed"> | 25 | <div class="results-filter collapse-transition" [ngbCollapse]="isSearchFilterCollapsed"> |
26 | <my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters> | 26 | <my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters> |
27 | |||
28 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
27 | </div> | 29 | </div> |
28 | </div> | 30 | </div> |
29 | 31 | ||
diff --git a/client/src/app/+search/search.component.scss b/client/src/app/+search/search.component.scss index fca704d27..b521825e5 100644 --- a/client/src/app/+search/search.component.scss +++ b/client/src/app/+search/search.component.scss | |||
@@ -15,6 +15,10 @@ | |||
15 | padding: 40px; | 15 | padding: 40px; |
16 | } | 16 | } |
17 | 17 | ||
18 | .alert-danger { | ||
19 | margin-top: 10px; | ||
20 | } | ||
21 | |||
18 | .results-header { | 22 | .results-header { |
19 | font-size: 16px; | 23 | font-size: 16px; |
20 | padding-bottom: 20px; | 24 | padding-bottom: 20px; |
diff --git a/client/src/app/+search/search.component.ts b/client/src/app/+search/search.component.ts index 235bbfa4c..250062e0c 100644 --- a/client/src/app/+search/search.component.ts +++ b/client/src/app/+search/search.component.ts | |||
@@ -4,6 +4,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core' | |||
4 | import { ActivatedRoute, Router } from '@angular/router' | 4 | import { ActivatedRoute, Router } from '@angular/router' |
5 | import { AuthService, HooksService, MetaService, Notifier, ServerService, User, UserService } from '@app/core' | 5 | import { AuthService, HooksService, MetaService, Notifier, ServerService, User, UserService } from '@app/core' |
6 | import { immutableAssign } from '@app/helpers' | 6 | import { immutableAssign } from '@app/helpers' |
7 | import { validateHost } from '@app/shared/form-validators/host-validators' | ||
7 | import { Video, VideoChannel } from '@app/shared/shared-main' | 8 | import { Video, VideoChannel } from '@app/shared/shared-main' |
8 | import { AdvancedSearch, SearchService } from '@app/shared/shared-search' | 9 | import { AdvancedSearch, SearchService } from '@app/shared/shared-search' |
9 | import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' | 10 | import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' |
@@ -16,6 +17,8 @@ import { HTMLServerConfig, SearchTargetType } from '@shared/models' | |||
16 | templateUrl: './search.component.html' | 17 | templateUrl: './search.component.html' |
17 | }) | 18 | }) |
18 | export class SearchComponent implements OnInit, OnDestroy { | 19 | export class SearchComponent implements OnInit, OnDestroy { |
20 | error: string | ||
21 | |||
19 | results: (Video | VideoChannel)[] = [] | 22 | results: (Video | VideoChannel)[] = [] |
20 | 23 | ||
21 | pagination = { | 24 | pagination = { |
@@ -89,8 +92,10 @@ export class SearchComponent implements OnInit, OnDestroy { | |||
89 | this.advancedSearch.searchTarget = this.getDefaultSearchTarget() | 92 | this.advancedSearch.searchTarget = this.getDefaultSearchTarget() |
90 | } | 93 | } |
91 | 94 | ||
92 | // Don't hide filters if we have some of them AND the user just came on the webpage | 95 | this.error = this.checkFieldsAndGetError() |
93 | this.isSearchFilterCollapsed = this.isInitialLoad === false || !this.advancedSearch.containsValues() | 96 | |
97 | // Don't hide filters if we have some of them AND the user just came on the webpage, or we have an error | ||
98 | this.isSearchFilterCollapsed = !this.error && (this.isInitialLoad === false || !this.advancedSearch.containsValues()) | ||
94 | this.isInitialLoad = false | 99 | this.isInitialLoad = false |
95 | 100 | ||
96 | this.search() | 101 | this.search() |
@@ -126,6 +131,9 @@ export class SearchComponent implements OnInit, OnDestroy { | |||
126 | } | 131 | } |
127 | 132 | ||
128 | search () { | 133 | search () { |
134 | this.error = this.checkFieldsAndGetError() | ||
135 | if (this.error) return | ||
136 | |||
129 | this.isSearching = true | 137 | this.isSearching = true |
130 | 138 | ||
131 | forkJoin([ | 139 | forkJoin([ |
@@ -280,7 +288,7 @@ export class SearchComponent implements OnInit, OnDestroy { | |||
280 | const params = { | 288 | const params = { |
281 | search: this.currentSearch, | 289 | search: this.currentSearch, |
282 | componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.channelsPerPage }), | 290 | componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.channelsPerPage }), |
283 | searchTarget: this.advancedSearch.searchTarget | 291 | advancedSearch: this.advancedSearch |
284 | } | 292 | } |
285 | 293 | ||
286 | return this.hooks.wrapObsFun( | 294 | return this.hooks.wrapObsFun( |
@@ -298,7 +306,7 @@ export class SearchComponent implements OnInit, OnDestroy { | |||
298 | const params = { | 306 | const params = { |
299 | search: this.currentSearch, | 307 | search: this.currentSearch, |
300 | componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.playlistsPerPage }), | 308 | componentPagination: immutableAssign(this.pagination, { itemsPerPage: this.playlistsPerPage }), |
301 | searchTarget: this.advancedSearch.searchTarget | 309 | advancedSearch: this.advancedSearch |
302 | } | 310 | } |
303 | 311 | ||
304 | return this.hooks.wrapObsFun( | 312 | return this.hooks.wrapObsFun( |
@@ -319,4 +327,12 @@ export class SearchComponent implements OnInit, OnDestroy { | |||
319 | 327 | ||
320 | return 'local' | 328 | return 'local' |
321 | } | 329 | } |
330 | |||
331 | private checkFieldsAndGetError () { | ||
332 | if (this.advancedSearch.host && !validateHost(this.advancedSearch.host)) { | ||
333 | return $localize`PeerTube instance host filter is invalid` | ||
334 | } | ||
335 | |||
336 | return undefined | ||
337 | } | ||
322 | } | 338 | } |