diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2019-12-04 17:12:23 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-12-05 09:06:01 +0100 |
commit | 25266908666d4d465e1c8ec90135eaa00c91732e (patch) | |
tree | a769c6d59f021b6b0a39766f4054a0d31a57a0c6 /client/src/app/search | |
parent | fee47735bde36d9b8d0aed6284e9e8c9f6697001 (diff) | |
download | PeerTube-25266908666d4d465e1c8ec90135eaa00c91732e.tar.gz PeerTube-25266908666d4d465e1c8ec90135eaa00c91732e.tar.zst PeerTube-25266908666d4d465e1c8ec90135eaa00c91732e.zip |
search filtering improvements per #1654
Diffstat (limited to 'client/src/app/search')
-rw-r--r-- | client/src/app/search/advanced-search.model.ts | 4 | ||||
-rw-r--r-- | client/src/app/search/search-filters.component.html | 82 | ||||
-rw-r--r-- | client/src/app/search/search-filters.component.scss | 92 | ||||
-rw-r--r-- | client/src/app/search/search-filters.component.ts | 45 | ||||
-rw-r--r-- | client/src/app/search/search.module.ts | 4 |
5 files changed, 210 insertions, 17 deletions
diff --git a/client/src/app/search/advanced-search.model.ts b/client/src/app/search/advanced-search.model.ts index e2a0253f4..50f00bc27 100644 --- a/client/src/app/search/advanced-search.model.ts +++ b/client/src/app/search/advanced-search.model.ts | |||
@@ -65,7 +65,7 @@ export class AdvancedSearch { | |||
65 | for (const k of Object.keys(obj)) { | 65 | for (const k of Object.keys(obj)) { |
66 | if (k === 'sort') continue // Exception | 66 | if (k === 'sort') continue // Exception |
67 | 67 | ||
68 | if (obj[k] !== undefined) return true | 68 | if (obj[k] !== undefined && obj[k] !== '') return true |
69 | } | 69 | } |
70 | 70 | ||
71 | return false | 71 | return false |
@@ -131,7 +131,7 @@ export class AdvancedSearch { | |||
131 | for (const k of Object.keys(obj)) { | 131 | for (const k of Object.keys(obj)) { |
132 | if (k === 'sort') continue // Exception | 132 | if (k === 'sort') continue // Exception |
133 | 133 | ||
134 | if (obj[k] !== undefined) acc++ | 134 | if (obj[k] !== undefined && obj[k] !== '') acc++ |
135 | } | 135 | } |
136 | 136 | ||
137 | return acc | 137 | return acc |
diff --git a/client/src/app/search/search-filters.component.html b/client/src/app/search/search-filters.component.html index 8220a990b..07fb2c048 100644 --- a/client/src/app/search/search-filters.component.html +++ b/client/src/app/search/search-filters.component.html | |||
@@ -3,7 +3,12 @@ | |||
3 | <div class="row"> | 3 | <div class="row"> |
4 | <div class="col-lg-4 col-md-6 col-xs-12"> | 4 | <div class="col-lg-4 col-md-6 col-xs-12"> |
5 | <div class="form-group"> | 5 | <div class="form-group"> |
6 | <div i18n class="radio-label">Sort</div> | 6 | <div class="radio-label label-container"> |
7 | <label i18n>Sort</label> | ||
8 | <button i18n class="reset-button reset-button-small" (click)="resetField('sort', '-match')" *ngIf="advancedSearch.sort !== '-match'"> | ||
9 | Reset | ||
10 | </button> | ||
11 | </div> | ||
7 | 12 | ||
8 | <div class="peertube-radio-container" *ngFor="let sort of sorts"> | 13 | <div class="peertube-radio-container" *ngFor="let sort of sorts"> |
9 | <input type="radio" name="sort" [id]="sort.id" [value]="sort.id" [(ngModel)]="advancedSearch.sort"> | 14 | <input type="radio" name="sort" [id]="sort.id" [value]="sort.id" [(ngModel)]="advancedSearch.sort"> |
@@ -12,20 +17,32 @@ | |||
12 | </div> | 17 | </div> |
13 | 18 | ||
14 | <div class="form-group"> | 19 | <div class="form-group"> |
15 | <div i18n class="radio-label">Published date</div> | 20 | <div class="radio-label label-container"> |
21 | <label i18n>Published date</label> | ||
22 | <button i18n class="reset-button reset-button-small" (click)="resetLocalField('publishedDateRange')" *ngIf="publishedDateRange !== undefined"> | ||
23 | Reset | ||
24 | </button> | ||
25 | </div> | ||
16 | 26 | ||
17 | <div class="peertube-radio-container" *ngFor="let date of publishedDateRanges"> | 27 | <div class="peertube-radio-container" *ngFor="let date of publishedDateRanges"> |
18 | <input type="radio" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange"> | 28 | <input type="radio" (change)="inputUpdated()" name="publishedDateRange" [id]="date.id" [value]="date.id" [(ngModel)]="publishedDateRange"> |
19 | <label [for]="date.id" class="radio">{{ date.label }}</label> | 29 | <label [for]="date.id" class="radio">{{ date.label }}</label> |
20 | </div> | 30 | </div> |
21 | </div> | 31 | </div> |
22 | 32 | ||
23 | <div class="form-group"> | 33 | <div class="form-group"> |
24 | <label i18n for="original-publication-after">Original publication year</label> | 34 | <div class="label-container"> |
35 | <label i18n for="original-publication-after">Original publication year</label> | ||
36 | <button i18n class="reset-button reset-button-small" (click)="resetOriginalPublicationYears()" *ngIf="originallyPublishedStartYear || originallyPublishedEndYear"> | ||
37 | Reset | ||
38 | </button> | ||
39 | </div> | ||
25 | 40 | ||
26 | <div class="row"> | 41 | <div class="row"> |
27 | <div class="col-sm-6"> | 42 | <div class="col-sm-6"> |
28 | <input | 43 | <input |
44 | (change)="inputUpdated()" | ||
45 | (keydown.enter)="$event.preventDefault()" | ||
29 | type="text" id="original-publication-after" name="original-publication-after" | 46 | type="text" id="original-publication-after" name="original-publication-after" |
30 | i18n-placeholder placeholder="After..." | 47 | i18n-placeholder placeholder="After..." |
31 | [(ngModel)]="originallyPublishedStartYear" | 48 | [(ngModel)]="originallyPublishedStartYear" |
@@ -33,6 +50,8 @@ | |||
33 | </div> | 50 | </div> |
34 | <div class="col-sm-6"> | 51 | <div class="col-sm-6"> |
35 | <input | 52 | <input |
53 | (change)="inputUpdated()" | ||
54 | (keydown.enter)="$event.preventDefault()" | ||
36 | type="text" id="original-publication-before" name="original-publication-before" | 55 | type="text" id="original-publication-before" name="original-publication-before" |
37 | i18n-placeholder placeholder="Before..." | 56 | i18n-placeholder placeholder="Before..." |
38 | [(ngModel)]="originallyPublishedEndYear" | 57 | [(ngModel)]="originallyPublishedEndYear" |
@@ -42,16 +61,26 @@ | |||
42 | </div> | 61 | </div> |
43 | 62 | ||
44 | <div class="form-group"> | 63 | <div class="form-group"> |
45 | <div i18n class="radio-label">Duration</div> | 64 | <div class="radio-label label-container"> |
65 | <label i18n>Duration</label> | ||
66 | <button i18n class="reset-button reset-button-small" (click)="resetLocalField('durationRange')" *ngIf="durationRange !== undefined"> | ||
67 | Reset | ||
68 | </button> | ||
69 | </div> | ||
46 | 70 | ||
47 | <div class="peertube-radio-container" *ngFor="let duration of durationRanges"> | 71 | <div class="peertube-radio-container" *ngFor="let duration of durationRanges"> |
48 | <input type="radio" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange"> | 72 | <input type="radio" (change)="inputUpdated()" name="durationRange" [id]="duration.id" [value]="duration.id" [(ngModel)]="durationRange"> |
49 | <label [for]="duration.id" class="radio">{{ duration.label }}</label> | 73 | <label [for]="duration.id" class="radio">{{ duration.label }}</label> |
50 | </div> | 74 | </div> |
51 | </div> | 75 | </div> |
52 | 76 | ||
53 | <div class="form-group"> | 77 | <div class="form-group"> |
54 | <div i18n class="radio-label">Display sensitive content</div> | 78 | <div class="radio-label label-container"> |
79 | <label i18n>Display sensitive content</label> | ||
80 | <button i18n class="reset-button reset-button-small" (click)="resetField('nsfw')" *ngIf="advancedSearch.nsfw !== undefined"> | ||
81 | Reset | ||
82 | </button> | ||
83 | </div> | ||
55 | 84 | ||
56 | <div class="peertube-radio-container"> | 85 | <div class="peertube-radio-container"> |
57 | <input type="radio" name="sensitiveContent" id="sensitiveContentYes" value="both" [(ngModel)]="advancedSearch.nsfw"> | 86 | <input type="radio" name="sensitiveContent" id="sensitiveContentYes" value="both" [(ngModel)]="advancedSearch.nsfw"> |
@@ -69,9 +98,12 @@ | |||
69 | <div class="col-lg-4 col-md-6 col-xs-12"> | 98 | <div class="col-lg-4 col-md-6 col-xs-12"> |
70 | <div class="form-group"> | 99 | <div class="form-group"> |
71 | <label i18n for="category">Category</label> | 100 | <label i18n for="category">Category</label> |
101 | <button i18n class="reset-button reset-button-small" (click)="resetField('categoryOneOf')" *ngIf="advancedSearch.categoryOneOf !== undefined"> | ||
102 | Reset | ||
103 | </button> | ||
72 | <div class="peertube-select-container"> | 104 | <div class="peertube-select-container"> |
73 | <select id="category" name="category" [(ngModel)]="advancedSearch.categoryOneOf"> | 105 | <select id="category" name="category" [(ngModel)]="advancedSearch.categoryOneOf"> |
74 | <option></option> | 106 | <option [value]="undefined" i18n>Any or no category set</option> |
75 | <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> | 107 | <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option> |
76 | </select> | 108 | </select> |
77 | </div> | 109 | </div> |
@@ -79,9 +111,12 @@ | |||
79 | 111 | ||
80 | <div class="form-group"> | 112 | <div class="form-group"> |
81 | <label i18n for="licence">Licence</label> | 113 | <label i18n for="licence">Licence</label> |
114 | <button i18n class="reset-button reset-button-small" (click)="resetField('licenceOneOf')" *ngIf="advancedSearch.licenceOneOf !== undefined"> | ||
115 | Reset | ||
116 | </button> | ||
82 | <div class="peertube-select-container"> | 117 | <div class="peertube-select-container"> |
83 | <select id="licence" name="licence" [(ngModel)]="advancedSearch.licenceOneOf"> | 118 | <select id="licence" name="licence" [(ngModel)]="advancedSearch.licenceOneOf"> |
84 | <option></option> | 119 | <option [value]="undefined" i18n>Any or no license set</option> |
85 | <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> | 120 | <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option> |
86 | </select> | 121 | </select> |
87 | </div> | 122 | </div> |
@@ -89,9 +124,12 @@ | |||
89 | 124 | ||
90 | <div class="form-group"> | 125 | <div class="form-group"> |
91 | <label i18n for="language">Language</label> | 126 | <label i18n for="language">Language</label> |
127 | <button i18n class="reset-button reset-button-small" (click)="resetField('languageOneOf')" *ngIf="advancedSearch.languageOneOf !== undefined"> | ||
128 | Reset | ||
129 | </button> | ||
92 | <div class="peertube-select-container"> | 130 | <div class="peertube-select-container"> |
93 | <select id="language" name="language" [(ngModel)]="advancedSearch.languageOneOf"> | 131 | <select id="language" name="language" [(ngModel)]="advancedSearch.languageOneOf"> |
94 | <option></option> | 132 | <option [value]="undefined" i18n>Any or no language set</option> |
95 | <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> | 133 | <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option> |
96 | </select> | 134 | </select> |
97 | </div> | 135 | </div> |
@@ -101,17 +139,37 @@ | |||
101 | <div class="col-lg-4 col-md-6 col-xs-12"> | 139 | <div class="col-lg-4 col-md-6 col-xs-12"> |
102 | <div class="form-group"> | 140 | <div class="form-group"> |
103 | <label i18n for="tagsAllOf">All of these tags</label> | 141 | <label i18n for="tagsAllOf">All of these tags</label> |
104 | <input type="text" name="tagsAllOf" id="tagsAllOf" [(ngModel)]="advancedSearch.tagsAllOf" /> | 142 | <button i18n class="reset-button reset-button-small" (click)="resetField('tagsAllOf')" *ngIf="advancedSearch.tagsAllOf"> |
143 | Reset | ||
144 | </button> | ||
145 | <tag-input | ||
146 | [(ngModel)]="advancedSearch.tagsAllOf" name="tagsAllOf" id="tagsAllOf" | ||
147 | [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" | ||
148 | i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a tag" | ||
149 | maxItems="5" modelAsStrings="true" | ||
150 | ></tag-input> | ||
105 | </div> | 151 | </div> |
106 | 152 | ||
107 | <div class="form-group"> | 153 | <div class="form-group"> |
108 | <label i18n for="tagsOneOf">One of these tags</label> | 154 | <label i18n for="tagsOneOf">One of these tags</label> |
109 | <input type="text" name="tagsOneOf" id="tagsOneOf" [(ngModel)]="advancedSearch.tagsOneOf" /> | 155 | <button i18n class="reset-button reset-button-small" (click)="resetField('tagsOneOf')" *ngIf="advancedSearch.tagsOneOf"> |
156 | Reset | ||
157 | </button> | ||
158 | <tag-input | ||
159 | [(ngModel)]="advancedSearch.tagsOneOf" name="tagsOneOf" id="tagsOneOf" | ||
160 | [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" | ||
161 | i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a tag" | ||
162 | maxItems="5" modelAsStrings="true" | ||
163 | ></tag-input> | ||
110 | </div> | 164 | </div> |
111 | </div> | 165 | </div> |
112 | </div> | 166 | </div> |
113 | 167 | ||
114 | <div class="submit-button"> | 168 | <div class="submit-button"> |
169 | <button i18n class="reset-button" (click)="reset()" *ngIf="advancedSearch.size()"> | ||
170 | Reset | ||
171 | </button> | ||
172 | |||
115 | <input type="submit" i18n-value value="Filter"> | 173 | <input type="submit" i18n-value value="Filter"> |
116 | </div> | 174 | </div> |
117 | </form> | 175 | </form> |
diff --git a/client/src/app/search/search-filters.component.scss b/client/src/app/search/search-filters.component.scss index cfc48fbef..99af2e4c5 100644 --- a/client/src/app/search/search-filters.component.scss +++ b/client/src/app/search/search-filters.component.scss | |||
@@ -19,6 +19,8 @@ form { | |||
19 | 19 | ||
20 | .peertube-select-container { | 20 | .peertube-select-container { |
21 | @include peertube-select-container(auto); | 21 | @include peertube-select-container(auto); |
22 | |||
23 | margin-bottom: 1rem; | ||
22 | } | 24 | } |
23 | 25 | ||
24 | .form-group { | 26 | .form-group { |
@@ -37,4 +39,92 @@ input[type=submit] { | |||
37 | 39 | ||
38 | .submit-button { | 40 | .submit-button { |
39 | text-align: right; | 41 | text-align: right; |
40 | } \ No newline at end of file | 42 | } |
43 | |||
44 | .reset-button { | ||
45 | @include peertube-button; | ||
46 | |||
47 | font-weight: $font-semibold; | ||
48 | display: inline-block; | ||
49 | padding: 0 10px 0 10px; | ||
50 | white-space: nowrap; | ||
51 | background: transparent; | ||
52 | |||
53 | margin-right: 1rem; | ||
54 | } | ||
55 | |||
56 | .reset-button-small { | ||
57 | font-size: 80%; | ||
58 | height: unset; | ||
59 | line-height: unset; | ||
60 | margin: unset; | ||
61 | margin-bottom: 0.5rem; | ||
62 | } | ||
63 | |||
64 | .label-container { | ||
65 | display: flex; | ||
66 | white-space: nowrap; | ||
67 | } | ||
68 | |||
69 | ::ng-deep { | ||
70 | .ng2-tag-input { | ||
71 | border: none !important; | ||
72 | } | ||
73 | |||
74 | .ng2-tags-container { | ||
75 | display: flex; | ||
76 | align-items: center; | ||
77 | border: 1px solid #C6C6C6; | ||
78 | border-radius: 3px; | ||
79 | padding: 5px !important; | ||
80 | height: max-content; | ||
81 | } | ||
82 | |||
83 | tag-input-form { | ||
84 | input { | ||
85 | height: 30px !important; | ||
86 | font-size: 12px !important; | ||
87 | |||
88 | background-color: var(--mainBackgroundColor) !important; | ||
89 | color: var(--mainForegroundColor) !important; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | tag { | ||
94 | background-color: $grey-background-color !important; | ||
95 | color: #000 !important; | ||
96 | border-radius: 3px !important; | ||
97 | font-size: 12px !important; | ||
98 | height: 30px !important; | ||
99 | line-height: 30px !important; | ||
100 | margin: 0 5px 0 0 !important; | ||
101 | cursor: default !important; | ||
102 | padding: 0 8px 0 10px !important; | ||
103 | |||
104 | div { | ||
105 | height: 100% !important; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | delete-icon { | ||
110 | cursor: pointer !important; | ||
111 | height: auto !important; | ||
112 | vertical-align: middle !important; | ||
113 | padding-left: 6px !important; | ||
114 | |||
115 | svg { | ||
116 | position: relative; | ||
117 | top: -1px; | ||
118 | height: auto !important; | ||
119 | vertical-align: middle !important; | ||
120 | |||
121 | path { | ||
122 | fill: $grey-foreground-color !important; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | &:hover { | ||
127 | transform: none !important; | ||
128 | } | ||
129 | } | ||
130 | } | ||
diff --git a/client/src/app/search/search-filters.component.ts b/client/src/app/search/search-filters.component.ts index 14a05b721..b64c965b1 100644 --- a/client/src/app/search/search-filters.component.ts +++ b/client/src/app/search/search-filters.component.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core' |
2 | import { ValidatorFn } from '@angular/forms' | ||
3 | import { VideoValidatorsService } from '@app/shared' | ||
2 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | 5 | import { I18n } from '@ngx-translate/i18n-polyfill' |
4 | import { AdvancedSearch } from '@app/search/advanced-search.model' | 6 | import { AdvancedSearch } from '@app/search/advanced-search.model' |
@@ -18,6 +20,9 @@ export class SearchFiltersComponent implements OnInit { | |||
18 | videoLicences: VideoConstant<number>[] = [] | 20 | videoLicences: VideoConstant<number>[] = [] |
19 | videoLanguages: VideoConstant<string>[] = [] | 21 | videoLanguages: VideoConstant<string>[] = [] |
20 | 22 | ||
23 | tagValidators: ValidatorFn[] | ||
24 | tagValidatorsMessages: { [ name: string ]: string } | ||
25 | |||
21 | publishedDateRanges: { id: string, label: string }[] = [] | 26 | publishedDateRanges: { id: string, label: string }[] = [] |
22 | sorts: { id: string, label: string }[] = [] | 27 | sorts: { id: string, label: string }[] = [] |
23 | durationRanges: { id: string, label: string }[] = [] | 28 | durationRanges: { id: string, label: string }[] = [] |
@@ -30,10 +35,17 @@ export class SearchFiltersComponent implements OnInit { | |||
30 | 35 | ||
31 | constructor ( | 36 | constructor ( |
32 | private i18n: I18n, | 37 | private i18n: I18n, |
38 | private videoValidatorsService: VideoValidatorsService, | ||
33 | private serverService: ServerService | 39 | private serverService: ServerService |
34 | ) { | 40 | ) { |
41 | this.tagValidators = this.videoValidatorsService.VIDEO_TAGS.VALIDATORS | ||
42 | this.tagValidatorsMessages = this.videoValidatorsService.VIDEO_TAGS.MESSAGES | ||
35 | this.publishedDateRanges = [ | 43 | this.publishedDateRanges = [ |
36 | { | 44 | { |
45 | id: undefined, | ||
46 | label: this.i18n('Any') | ||
47 | }, | ||
48 | { | ||
37 | id: 'today', | 49 | id: 'today', |
38 | label: this.i18n('Today') | 50 | label: this.i18n('Today') |
39 | }, | 51 | }, |
@@ -53,6 +65,10 @@ export class SearchFiltersComponent implements OnInit { | |||
53 | 65 | ||
54 | this.durationRanges = [ | 66 | this.durationRanges = [ |
55 | { | 67 | { |
68 | id: undefined, | ||
69 | label: this.i18n('Any') | ||
70 | }, | ||
71 | { | ||
56 | id: 'short', | 72 | id: 'short', |
57 | label: this.i18n('Short (< 4 min)') | 73 | label: this.i18n('Short (< 4 min)') |
58 | }, | 74 | }, |
@@ -92,11 +108,14 @@ export class SearchFiltersComponent implements OnInit { | |||
92 | this.loadOriginallyPublishedAtYears() | 108 | this.loadOriginallyPublishedAtYears() |
93 | } | 109 | } |
94 | 110 | ||
95 | formUpdated () { | 111 | inputUpdated () { |
96 | this.updateModelFromDurationRange() | 112 | this.updateModelFromDurationRange() |
97 | this.updateModelFromPublishedRange() | 113 | this.updateModelFromPublishedRange() |
98 | this.updateModelFromOriginallyPublishedAtYears() | 114 | this.updateModelFromOriginallyPublishedAtYears() |
115 | } | ||
99 | 116 | ||
117 | formUpdated () { | ||
118 | this.inputUpdated() | ||
100 | this.filtered.emit(this.advancedSearch) | 119 | this.filtered.emit(this.advancedSearch) |
101 | } | 120 | } |
102 | 121 | ||
@@ -216,4 +235,26 @@ export class SearchFiltersComponent implements OnInit { | |||
216 | this.advancedSearch.startDate = date.toISOString() | 235 | this.advancedSearch.startDate = date.toISOString() |
217 | } | 236 | } |
218 | 237 | ||
238 | private reset () { | ||
239 | this.advancedSearch.reset() | ||
240 | this.durationRange = undefined | ||
241 | this.publishedDateRange = undefined | ||
242 | this.originallyPublishedStartYear = undefined | ||
243 | this.originallyPublishedEndYear = undefined | ||
244 | this.inputUpdated() | ||
245 | } | ||
246 | |||
247 | private resetField (fieldName: string, value?: any) { | ||
248 | this.advancedSearch[fieldName] = value | ||
249 | } | ||
250 | |||
251 | private resetLocalField (fieldName: string, value?: any) { | ||
252 | this[fieldName] = value | ||
253 | this.inputUpdated() | ||
254 | } | ||
255 | |||
256 | private resetOriginalPublicationYears () { | ||
257 | this.originallyPublishedStartYear = this.originallyPublishedEndYear = undefined | ||
258 | } | ||
259 | |||
219 | } | 260 | } |
diff --git a/client/src/app/search/search.module.ts b/client/src/app/search/search.module.ts index 8b791621e..3b0fd6ee2 100644 --- a/client/src/app/search/search.module.ts +++ b/client/src/app/search/search.module.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { NgModule } from '@angular/core' | 1 | import { NgModule } from '@angular/core' |
2 | import { TagInputModule } from 'ngx-chips' | ||
2 | import { SharedModule } from '../shared' | 3 | import { SharedModule } from '../shared' |
3 | import { SearchComponent } from '@app/search/search.component' | 4 | import { SearchComponent } from '@app/search/search.component' |
4 | import { SearchService } from '@app/search/search.service' | 5 | import { SearchService } from '@app/search/search.service' |
@@ -7,6 +8,8 @@ import { SearchFiltersComponent } from '@app/search/search-filters.component' | |||
7 | 8 | ||
8 | @NgModule({ | 9 | @NgModule({ |
9 | imports: [ | 10 | imports: [ |
11 | TagInputModule, | ||
12 | |||
10 | SearchRoutingModule, | 13 | SearchRoutingModule, |
11 | SharedModule | 14 | SharedModule |
12 | ], | 15 | ], |
@@ -17,6 +20,7 @@ import { SearchFiltersComponent } from '@app/search/search-filters.component' | |||
17 | ], | 20 | ], |
18 | 21 | ||
19 | exports: [ | 22 | exports: [ |
23 | TagInputModule, | ||
20 | SearchComponent | 24 | SearchComponent |
21 | ], | 25 | ], |
22 | 26 | ||