Fix videos list margin with hidden menu
[oweals/peertube.git] / client / src / app / search / search-filters.component.ts
1 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
2 import { ServerService } from '@app/core'
3 import { I18n } from '@ngx-translate/i18n-polyfill'
4 import { AdvancedSearch } from '@app/search/advanced-search.model'
5 import { VideoConstant } from '../../../../shared'
6
7 @Component({
8   selector: 'my-search-filters',
9   styleUrls: [ './search-filters.component.scss' ],
10   templateUrl: './search-filters.component.html'
11 })
12 export class SearchFiltersComponent implements OnInit {
13   @Input() advancedSearch: AdvancedSearch = new AdvancedSearch()
14
15   @Output() filtered = new EventEmitter<AdvancedSearch>()
16
17   videoCategories: VideoConstant<number>[] = []
18   videoLicences: VideoConstant<number>[] = []
19   videoLanguages: VideoConstant<string>[] = []
20
21   publishedDateRanges: { id: string, label: string }[] = []
22   sorts: { id: string, label: string }[] = []
23   durationRanges: { id: string, label: string }[] = []
24
25   publishedDateRange: string
26   durationRange: string
27
28   originallyPublishedStartYear: string
29   originallyPublishedEndYear: string
30
31   constructor (
32     private i18n: I18n,
33     private serverService: ServerService
34   ) {
35     this.publishedDateRanges = [
36       {
37         id: 'today',
38         label: this.i18n('Today')
39       },
40       {
41         id: 'last_7days',
42         label: this.i18n('Last 7 days')
43       },
44       {
45         id: 'last_30days',
46         label: this.i18n('Last 30 days')
47       },
48       {
49         id: 'last_365days',
50         label: this.i18n('Last 365 days')
51       }
52     ]
53
54     this.durationRanges = [
55       {
56         id: 'short',
57         label: this.i18n('Short (< 4 min)')
58       },
59       {
60         id: 'long',
61         label: this.i18n('Long (> 10 min)')
62       },
63       {
64         id: 'medium',
65         label: this.i18n('Medium (4-10 min)')
66       }
67     ]
68
69     this.sorts = [
70       {
71         id: '-match',
72         label: this.i18n('Relevance')
73       },
74       {
75         id: '-publishedAt',
76         label: this.i18n('Publish date')
77       },
78       {
79         id: '-views',
80         label: this.i18n('Views')
81       }
82     ]
83   }
84
85   ngOnInit () {
86     this.videoCategories = this.serverService.getVideoCategories()
87     this.videoLicences = this.serverService.getVideoLicences()
88     this.videoLanguages = this.serverService.getVideoLanguages()
89
90     this.loadFromDurationRange()
91     this.loadFromPublishedRange()
92     this.loadOriginallyPublishedAtYears()
93   }
94
95   formUpdated () {
96     this.updateModelFromDurationRange()
97     this.updateModelFromPublishedRange()
98     this.updateModelFromOriginallyPublishedAtYears()
99
100     this.filtered.emit(this.advancedSearch)
101   }
102
103   private loadOriginallyPublishedAtYears () {
104     this.originallyPublishedStartYear = this.advancedSearch.originallyPublishedStartDate
105       ? new Date(this.advancedSearch.originallyPublishedStartDate).getFullYear().toString()
106       : null
107
108     this.originallyPublishedEndYear = this.advancedSearch.originallyPublishedEndDate
109       ? new Date(this.advancedSearch.originallyPublishedEndDate).getFullYear().toString()
110       : null
111   }
112
113   private loadFromDurationRange () {
114     if (this.advancedSearch.durationMin || this.advancedSearch.durationMax) {
115       const fourMinutes = 60 * 4
116       const tenMinutes = 60 * 10
117
118       if (this.advancedSearch.durationMin === fourMinutes && this.advancedSearch.durationMax === tenMinutes) {
119         this.durationRange = 'medium'
120       } else if (this.advancedSearch.durationMax === fourMinutes) {
121         this.durationRange = 'short'
122       } else if (this.advancedSearch.durationMin === tenMinutes) {
123         this.durationRange = 'long'
124       }
125     }
126   }
127
128   private loadFromPublishedRange () {
129     if (this.advancedSearch.startDate) {
130       const date = new Date(this.advancedSearch.startDate)
131       const now = new Date()
132
133       const diff = Math.abs(date.getTime() - now.getTime())
134
135       const dayMS = 1000 * 3600 * 24
136       const numberOfDays = diff / dayMS
137
138       if (numberOfDays >= 365) this.publishedDateRange = 'last_365days'
139       else if (numberOfDays >= 30) this.publishedDateRange = 'last_30days'
140       else if (numberOfDays >= 7) this.publishedDateRange = 'last_7days'
141       else if (numberOfDays >= 0) this.publishedDateRange = 'today'
142     }
143   }
144
145   private updateModelFromOriginallyPublishedAtYears () {
146     const baseDate = new Date()
147     baseDate.setHours(0, 0, 0, 0)
148     baseDate.setMonth(0, 1)
149
150     if (this.originallyPublishedStartYear) {
151       const year = parseInt(this.originallyPublishedStartYear, 10)
152       const start = new Date(baseDate)
153       start.setFullYear(year)
154
155       this.advancedSearch.originallyPublishedStartDate = start.toISOString()
156     } else {
157       this.advancedSearch.originallyPublishedStartDate = null
158     }
159
160     if (this.originallyPublishedEndYear) {
161       const year = parseInt(this.originallyPublishedEndYear, 10)
162       const end = new Date(baseDate)
163       end.setFullYear(year)
164
165       this.advancedSearch.originallyPublishedEndDate = end.toISOString()
166     } else {
167       this.advancedSearch.originallyPublishedEndDate = null
168     }
169   }
170
171   private updateModelFromDurationRange () {
172     if (!this.durationRange) return
173
174     const fourMinutes = 60 * 4
175     const tenMinutes = 60 * 10
176
177     switch (this.durationRange) {
178       case 'short':
179         this.advancedSearch.durationMin = undefined
180         this.advancedSearch.durationMax = fourMinutes
181         break
182
183       case 'medium':
184         this.advancedSearch.durationMin = fourMinutes
185         this.advancedSearch.durationMax = tenMinutes
186         break
187
188       case 'long':
189         this.advancedSearch.durationMin = tenMinutes
190         this.advancedSearch.durationMax = undefined
191         break
192     }
193   }
194
195   private updateModelFromPublishedRange () {
196     if (!this.publishedDateRange) return
197
198     // today
199     const date = new Date()
200     date.setHours(0, 0, 0, 0)
201
202     switch (this.publishedDateRange) {
203       case 'last_7days':
204         date.setDate(date.getDate() - 7)
205         break
206
207       case 'last_30days':
208         date.setDate(date.getDate() - 30)
209         break
210
211       case 'last_365days':
212         date.setDate(date.getDate() - 365)
213         break
214     }
215
216     this.advancedSearch.startDate = date.toISOString()
217   }
218
219 }