diff options
Diffstat (limited to 'client')
3 files changed, 90 insertions, 8 deletions
diff --git a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html index ba05073cf..cffa7a40e 100644 --- a/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html +++ b/client/src/app/+admin/moderation/video-abuse-list/video-abuse-list.component.html | |||
@@ -19,8 +19,8 @@ | |||
19 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:pending' }" class="dropdown-item" i18n>Unsolved reports</a> | 19 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:pending' }" class="dropdown-item" i18n>Unsolved reports</a> |
20 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:accepted' }" class="dropdown-item" i18n>Accepted reports</a> | 20 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:accepted' }" class="dropdown-item" i18n>Accepted reports</a> |
21 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:rejected' }" class="dropdown-item" i18n>Refused reports</a> | 21 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:rejected' }" class="dropdown-item" i18n>Refused reports</a> |
22 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'is:blacklisted' }" class="dropdown-item" i18n>Reports with blacklisted videos</a> | 22 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:blacklisted' }" class="dropdown-item" i18n>Reports with blacklisted videos</a> |
23 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'is:deleted' }" class="dropdown-item" i18n>Reports with deleted videos</a> | 23 | <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:deleted' }" class="dropdown-item" i18n>Reports with deleted videos</a> |
24 | </div> | 24 | </div> |
25 | </div> | 25 | </div> |
26 | <input | 26 | <input |
diff --git a/client/src/app/shared/rest/rest.service.ts b/client/src/app/shared/rest/rest.service.ts index 5bd2b5e43..cd6db1f3c 100644 --- a/client/src/app/shared/rest/rest.service.ts +++ b/client/src/app/shared/rest/rest.service.ts | |||
@@ -1,10 +1,21 @@ | |||
1 | import { Injectable } from '@angular/core' | ||
2 | import { HttpParams } from '@angular/common/http' | ||
3 | import { SortMeta } from 'primeng/api' | 1 | import { SortMeta } from 'primeng/api' |
4 | import { ComponentPagination, ComponentPaginationLight } from './component-pagination.model' | 2 | import { HttpParams } from '@angular/common/http' |
5 | 3 | import { Injectable } from '@angular/core' | |
4 | import { ComponentPaginationLight } from './component-pagination.model' | ||
6 | import { RestPagination } from './rest-pagination' | 5 | import { RestPagination } from './rest-pagination' |
7 | 6 | ||
7 | interface QueryStringFilterPrefixes { | ||
8 | [key: string]: { | ||
9 | prefix: string | ||
10 | handler?: (v: string) => string | number | ||
11 | multiple?: boolean | ||
12 | } | ||
13 | } | ||
14 | |||
15 | type ParseQueryStringFilterResult = { | ||
16 | [key: string]: string | number | (string | number)[] | ||
17 | } | ||
18 | |||
8 | @Injectable() | 19 | @Injectable() |
9 | export class RestService { | 20 | export class RestService { |
10 | 21 | ||
@@ -53,4 +64,48 @@ export class RestService { | |||
53 | 64 | ||
54 | return { start, count } | 65 | return { start, count } |
55 | } | 66 | } |
67 | |||
68 | parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes): ParseQueryStringFilterResult { | ||
69 | if (!q) return {} | ||
70 | |||
71 | // Tokenize the strings using spaces | ||
72 | const tokens = q.split(' ').filter(token => !!token) | ||
73 | |||
74 | // Build prefix array | ||
75 | const prefixeStrings = Object.values(prefixes) | ||
76 | .map(p => p.prefix) | ||
77 | |||
78 | // Search is the querystring minus defined filters | ||
79 | const searchTokens = tokens.filter(t => { | ||
80 | return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false) | ||
81 | }) | ||
82 | |||
83 | const additionalFilters: ParseQueryStringFilterResult = {} | ||
84 | |||
85 | for (const prefixKey of Object.keys(prefixes)) { | ||
86 | const prefixObj = prefixes[prefixKey] | ||
87 | const prefix = prefixObj.prefix | ||
88 | |||
89 | const matchedTokens = tokens.filter(t => t.startsWith(prefix)) | ||
90 | .map(t => t.slice(prefix.length)) // Keep the value filter | ||
91 | .map(t => { | ||
92 | if (prefixObj.handler) return prefixObj.handler(t) | ||
93 | |||
94 | return t | ||
95 | }) | ||
96 | .filter(t => !!t) | ||
97 | |||
98 | if (matchedTokens.length === 0) continue | ||
99 | |||
100 | additionalFilters[prefixKey] = prefixObj.multiple === true | ||
101 | ? matchedTokens | ||
102 | : matchedTokens[0] | ||
103 | } | ||
104 | |||
105 | return { | ||
106 | search: searchTokens.join(' '), | ||
107 | |||
108 | ...additionalFilters | ||
109 | } | ||
110 | } | ||
56 | } | 111 | } |
diff --git a/client/src/app/shared/video-abuse/video-abuse.service.ts b/client/src/app/shared/video-abuse/video-abuse.service.ts index 1ab6b5376..700a30239 100644 --- a/client/src/app/shared/video-abuse/video-abuse.service.ts +++ b/client/src/app/shared/video-abuse/video-abuse.service.ts | |||
@@ -3,7 +3,7 @@ import { HttpClient, HttpParams } from '@angular/common/http' | |||
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { SortMeta } from 'primeng/api' | 4 | import { SortMeta } from 'primeng/api' |
5 | import { Observable } from 'rxjs' | 5 | import { Observable } from 'rxjs' |
6 | import { ResultList, VideoAbuse, VideoAbuseUpdate } from '../../../../../shared' | 6 | import { ResultList, VideoAbuse, VideoAbuseUpdate, VideoAbuseState } from '../../../../../shared' |
7 | import { environment } from '../../../environments/environment' | 7 | import { environment } from '../../../environments/environment' |
8 | import { RestExtractor, RestPagination, RestService } from '../rest' | 8 | import { RestExtractor, RestPagination, RestService } from '../rest' |
9 | 9 | ||
@@ -28,7 +28,34 @@ export class VideoAbuseService { | |||
28 | let params = new HttpParams() | 28 | let params = new HttpParams() |
29 | params = this.restService.addRestGetParams(params, pagination, sort) | 29 | params = this.restService.addRestGetParams(params, pagination, sort) |
30 | 30 | ||
31 | if (search) params = params.append('search', search) | 31 | if (search) { |
32 | const filters = this.restService.parseQueryStringFilter(search, { | ||
33 | id: { prefix: '#' }, | ||
34 | state: { | ||
35 | prefix: 'state:', | ||
36 | handler: v => { | ||
37 | if (v === 'accepted') return VideoAbuseState.ACCEPTED | ||
38 | if (v === 'pending') return VideoAbuseState.PENDING | ||
39 | if (v === 'rejected') return VideoAbuseState.REJECTED | ||
40 | |||
41 | return undefined | ||
42 | } | ||
43 | }, | ||
44 | videoIs: { | ||
45 | prefix: 'videoIs:', | ||
46 | handler: v => { | ||
47 | if (v === 'deleted') return v | ||
48 | if (v === 'blacklisted') return v | ||
49 | |||
50 | return undefined | ||
51 | } | ||
52 | }, | ||
53 | searchReporter: { prefix: 'reporter:' }, | ||
54 | searchReportee: { prefix: 'reportee:' } | ||
55 | }) | ||
56 | |||
57 | params = this.restService.addObjectParams(params, filters) | ||
58 | } | ||
32 | 59 | ||
33 | return this.authHttp.get<ResultList<VideoAbuse>>(url, { params }) | 60 | return this.authHttp.get<ResultList<VideoAbuse>>(url, { params }) |
34 | .pipe( | 61 | .pipe( |