aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts10
-rw-r--r--client/src/app/shared/shared-forms/advanced-input-filter.component.html6
-rw-r--r--client/src/app/shared/shared-forms/advanced-input-filter.component.scss23
-rw-r--r--client/src/app/shared/shared-forms/advanced-input-filter.component.ts61
4 files changed, 89 insertions, 11 deletions
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
index 10f5861b9..b902726fa 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
+++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
@@ -39,23 +39,23 @@ export class AbuseListTableComponent extends RestTable implements OnInit {
39 title: $localize`Advanced filters`, 39 title: $localize`Advanced filters`,
40 children: [ 40 children: [
41 { 41 {
42 queryParams: { search: 'state:pending' }, 42 value: 'state:pending',
43 label: $localize`Unsolved reports` 43 label: $localize`Unsolved reports`
44 }, 44 },
45 { 45 {
46 queryParams: { search: 'state:accepted' }, 46 value: 'state:accepted',
47 label: $localize`Accepted reports` 47 label: $localize`Accepted reports`
48 }, 48 },
49 { 49 {
50 queryParams: { search: 'state:rejected' }, 50 value: 'state:rejected',
51 label: $localize`Refused reports` 51 label: $localize`Refused reports`
52 }, 52 },
53 { 53 {
54 queryParams: { search: 'videoIs:blacklisted' }, 54 value: 'videoIs:blacklisted',
55 label: $localize`Reports with blocked videos` 55 label: $localize`Reports with blocked videos`
56 }, 56 },
57 { 57 {
58 queryParams: { search: 'videoIs:deleted' }, 58 value: 'videoIs:deleted',
59 label: $localize`Reports with deleted videos` 59 label: $localize`Reports with deleted videos`
60 } 60 }
61 ] 61 ]
diff --git a/client/src/app/shared/shared-forms/advanced-input-filter.component.html b/client/src/app/shared/shared-forms/advanced-input-filter.component.html
index c662b9bb6..7031cb53b 100644
--- a/client/src/app/shared/shared-forms/advanced-input-filter.component.html
+++ b/client/src/app/shared/shared-forms/advanced-input-filter.component.html
@@ -8,9 +8,11 @@
8 <ng-container *ngFor="let group of filters"> 8 <ng-container *ngFor="let group of filters">
9 <h6 class="dropdown-header">{{ group.title }}</h6> 9 <h6 class="dropdown-header">{{ group.title }}</h6>
10 10
11 <a *ngFor="let filter of group.children" [routerLink]="[ '.' ]" [queryParams]="filter.queryParams" class="dropdown-item"> 11 <button *ngFor="let filter of group.children" (click)="onFilterClick(filter)" class="dropdown-item">
12 <my-global-icon [ngClass]="{ 'no-visible': !isFilterEnabled(filter) }" iconName="tick"></my-global-icon>
13
12 {{ filter.label }} 14 {{ filter.label }}
13 </a> 15 </button>
14 </ng-container> 16 </ng-container>
15 </div> 17 </div>
16 </div> 18 </div>
diff --git a/client/src/app/shared/shared-forms/advanced-input-filter.component.scss b/client/src/app/shared/shared-forms/advanced-input-filter.component.scss
index 07a43761c..ee1b3b508 100644
--- a/client/src/app/shared/shared-forms/advanced-input-filter.component.scss
+++ b/client/src/app/shared/shared-forms/advanced-input-filter.component.scss
@@ -1,6 +1,10 @@
1@use '_variables' as *; 1@use '_variables' as *;
2@use '_mixins' as *; 2@use '_mixins' as *;
3 3
4.dropdown-item {
5 font-size: 14px;
6}
7
4input { 8input {
5 @include peertube-input-text(250px); 9 @include peertube-input-text(250px);
6} 10}
@@ -8,3 +12,22 @@ input {
8.input-group-text { 12.input-group-text {
9 background-color: transparent; 13 background-color: transparent;
10} 14}
15
16my-global-icon {
17 $size: 18px;
18 $margin: 2px;
19
20 @include margin-right($margin);
21
22 opacity: 1;
23 width: 18px;
24 height: 18px;
25
26
27 &.no-visible {
28 @include margin-right($size + $margin);
29
30 width: 0;
31 height: 0;
32 }
33}
diff --git a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
index a12dddf7a..d8aeaa0fa 100644
--- a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
+++ b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
@@ -3,14 +3,17 @@ import { Subject } from 'rxjs'
3import { debounceTime, distinctUntilChanged } from 'rxjs/operators' 3import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
4import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output } from '@angular/core' 4import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
5import { ActivatedRoute, Params, Router } from '@angular/router' 5import { ActivatedRoute, Params, Router } from '@angular/router'
6import { RestService } from '@app/core'
6 7
7export type AdvancedInputFilter = { 8export type AdvancedInputFilter = {
8 title: string 9 title: string
9 10
10 children: { 11 children: AdvancedInputFilterChild[]
11 label: string 12}
12 queryParams: Params 13
13 }[] 14export type AdvancedInputFilterChild = {
15 label: string
16 value: string
14} 17}
15 18
16const logger = debug('peertube:AdvancedInputFilterComponent') 19const logger = debug('peertube:AdvancedInputFilterComponent')
@@ -28,6 +31,8 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
28 31
29 searchValue: string 32 searchValue: string
30 33
34 private enabledFilters = new Set<string>()
35
31 private searchStream: Subject<string> 36 private searchStream: Subject<string>
32 37
33 private viewInitialized = false 38 private viewInitialized = false
@@ -35,6 +40,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
35 40
36 constructor ( 41 constructor (
37 private route: ActivatedRoute, 42 private route: ActivatedRoute,
43 private restService: RestService,
38 private router: Router 44 private router: Router
39 ) { } 45 ) { }
40 46
@@ -62,6 +68,18 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
62 return this.filters && this.filters.length !== 0 68 return this.filters && this.filters.length !== 0
63 } 69 }
64 70
71 isFilterEnabled (filter: AdvancedInputFilterChild) {
72 return this.enabledFilters.has(filter.value)
73 }
74
75 onFilterClick (filter: AdvancedInputFilterChild) {
76 const newSearch = this.isFilterEnabled(filter)
77 ? this.removeFilterToSearch(this.searchValue, filter)
78 : this.addFilterToSearch(this.searchValue, filter)
79
80 this.router.navigate([ '.' ], { relativeTo: this.route, queryParams: { search: newSearch.trim() } })
81 }
82
65 private scheduleSearchUpdate (value: string) { 83 private scheduleSearchUpdate (value: string) {
66 this.searchValue = value 84 this.searchValue = value
67 this.searchStream.next(this.searchValue) 85 this.searchStream.next(this.searchValue)
@@ -71,6 +89,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
71 this.searchValue = value 89 this.searchValue = value
72 90
73 this.setQueryParams(this.searchValue) 91 this.setQueryParams(this.searchValue)
92 this.parseFilters(this.searchValue)
74 this.emitSearch() 93 this.emitSearch()
75 } 94 }
76 95
@@ -84,6 +103,9 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
84 if (this.searchValue === search) return 103 if (this.searchValue === search) return
85 104
86 this.searchValue = search 105 this.searchValue = search
106
107 this.parseFilters(this.searchValue)
108
87 this.emitSearch() 109 this.emitSearch()
88 }) 110 })
89 } 111 }
@@ -98,6 +120,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
98 ) 120 )
99 .subscribe(() => { 121 .subscribe(() => {
100 this.setQueryParams(this.searchValue) 122 this.setQueryParams(this.searchValue)
123 this.parseFilters(this.searchValue)
101 124
102 this.emitSearch() 125 this.emitSearch()
103 }) 126 })
@@ -120,4 +143,34 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
120 if (search) Object.assign(queryParams, { search }) 143 if (search) Object.assign(queryParams, { search })
121 this.router.navigate([ ], { queryParams }) 144 this.router.navigate([ ], { queryParams })
122 } 145 }
146
147 private removeFilterToSearch (search: string, removedFilter: AdvancedInputFilterChild) {
148 return search.replace(removedFilter.value, '')
149 }
150
151 private addFilterToSearch (search: string, newFilter: AdvancedInputFilterChild) {
152 const prefix = newFilter.value.split(':').shift()
153
154 // Tokenize search and remove a potential existing filter
155 const tokens = this.restService.tokenizeString(search)
156 .filter(t => !t.startsWith(prefix))
157
158 tokens.push(newFilter.value)
159
160 return tokens.join(' ')
161 }
162
163 private parseFilters (search: string) {
164 const tokens = this.restService.tokenizeString(search)
165
166 this.enabledFilters = new Set()
167
168 for (const group of this.filters) {
169 for (const filter of group.children) {
170 if (tokens.includes(filter.value)) {
171 this.enabledFilters.add(filter.value)
172 }
173 }
174 }
175 }
123} 176}