]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
First implem global search
[github/Chocobozzz/PeerTube.git] / client / src / app / +admin / config / edit-custom-config / edit-custom-config.component.ts
1 import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core'
2 import { ConfigService } from '@app/+admin/config/shared/config.service'
3 import { ServerService } from '@app/core/server/server.service'
4 import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } from '@app/shared'
5 import { Notifier } from '@app/core'
6 import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
7 import { I18n } from '@ngx-translate/i18n-polyfill'
8 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
9 import { SelectItem } from 'primeng/api'
10 import { forkJoin } from 'rxjs'
11 import { ServerConfig } from '@shared/models'
12 import { ViewportScroller } from '@angular/common'
13 import { NgbNav } from '@ng-bootstrap/ng-bootstrap'
14
15 @Component({
16 selector: 'my-edit-custom-config',
17 templateUrl: './edit-custom-config.component.html',
18 styleUrls: [ './edit-custom-config.component.scss' ]
19 })
20 export class EditCustomConfigComponent extends FormReactive implements OnInit, AfterViewChecked {
21 // FIXME: use built-in router
22 @ViewChild('nav') nav: NgbNav
23
24 initDone = false
25 customConfig: CustomConfig
26
27 resolutions: { id: string, label: string, description?: string }[] = []
28 transcodingThreadOptions: { label: string, value: number }[] = []
29
30 languageItems: SelectItem[] = []
31 categoryItems: SelectItem[] = []
32
33 private serverConfig: ServerConfig
34
35 constructor (
36 private viewportScroller: ViewportScroller,
37 protected formValidatorService: FormValidatorService,
38 private customConfigValidatorsService: CustomConfigValidatorsService,
39 private userValidatorsService: UserValidatorsService,
40 private notifier: Notifier,
41 private configService: ConfigService,
42 private serverService: ServerService,
43 private i18n: I18n
44 ) {
45 super()
46
47 this.resolutions = [
48 {
49 id: '0p',
50 label: this.i18n('Audio-only'),
51 description: this.i18n('A <code>.mp4</code> that keeps the original audio track, with no video')
52 },
53 {
54 id: '240p',
55 label: this.i18n('240p')
56 },
57 {
58 id: '360p',
59 label: this.i18n('360p')
60 },
61 {
62 id: '480p',
63 label: this.i18n('480p')
64 },
65 {
66 id: '720p',
67 label: this.i18n('720p')
68 },
69 {
70 id: '1080p',
71 label: this.i18n('1080p')
72 },
73 {
74 id: '2160p',
75 label: this.i18n('2160p')
76 }
77 ]
78
79 this.transcodingThreadOptions = [
80 { value: 0, label: this.i18n('Auto (via ffmpeg)') },
81 { value: 1, label: '1' },
82 { value: 2, label: '2' },
83 { value: 4, label: '4' },
84 { value: 8, label: '8' }
85 ]
86 }
87
88 get videoQuotaOptions () {
89 return this.configService.videoQuotaOptions
90 }
91
92 get videoQuotaDailyOptions () {
93 return this.configService.videoQuotaDailyOptions
94 }
95
96 get availableThemes () {
97 return this.serverConfig.theme.registered
98 .map(t => t.name)
99 }
100
101 getResolutionKey (resolution: string) {
102 return 'transcoding.resolutions.' + resolution
103 }
104
105 ngOnInit () {
106 this.serverConfig = this.serverService.getTmpConfig()
107 this.serverService.getConfig()
108 .subscribe(config => this.serverConfig = config)
109
110 const formGroupData: { [key in keyof CustomConfig ]: any } = {
111 instance: {
112 name: this.customConfigValidatorsService.INSTANCE_NAME,
113 shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
114 description: null,
115
116 isNSFW: false,
117 defaultNSFWPolicy: null,
118
119 terms: null,
120 codeOfConduct: null,
121
122 creationReason: null,
123 moderationInformation: null,
124 administrator: null,
125 maintenanceLifetime: null,
126 businessModel: null,
127
128 hardwareInformation: null,
129
130 categories: null,
131 languages: null,
132
133 defaultClientRoute: null,
134
135 customizations: {
136 javascript: null,
137 css: null
138 }
139 },
140 theme: {
141 default: null
142 },
143 services: {
144 twitter: {
145 username: this.customConfigValidatorsService.SERVICES_TWITTER_USERNAME,
146 whitelisted: null
147 }
148 },
149 cache: {
150 previews: {
151 size: this.customConfigValidatorsService.CACHE_PREVIEWS_SIZE
152 },
153 captions: {
154 size: this.customConfigValidatorsService.CACHE_CAPTIONS_SIZE
155 }
156 },
157 signup: {
158 enabled: null,
159 limit: this.customConfigValidatorsService.SIGNUP_LIMIT,
160 requiresEmailVerification: null
161 },
162 import: {
163 videos: {
164 http: {
165 enabled: null
166 },
167 torrent: {
168 enabled: null
169 }
170 }
171 },
172 admin: {
173 email: this.customConfigValidatorsService.ADMIN_EMAIL
174 },
175 contactForm: {
176 enabled: null
177 },
178 user: {
179 videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
180 videoQuotaDaily: this.userValidatorsService.USER_VIDEO_QUOTA_DAILY
181 },
182 transcoding: {
183 enabled: null,
184 threads: this.customConfigValidatorsService.TRANSCODING_THREADS,
185 allowAdditionalExtensions: null,
186 allowAudioFiles: null,
187 resolutions: {},
188 hls: {
189 enabled: null
190 },
191 webtorrent: {
192 enabled: null
193 }
194 },
195 autoBlacklist: {
196 videos: {
197 ofUsers: {
198 enabled: null
199 }
200 }
201 },
202 followers: {
203 instance: {
204 enabled: null,
205 manualApproval: null
206 }
207 },
208 followings: {
209 instance: {
210 autoFollowBack: {
211 enabled: null
212 },
213 autoFollowIndex: {
214 enabled: null,
215 indexUrl: this.customConfigValidatorsService.INDEX_URL
216 }
217 }
218 },
219 broadcastMessage: {
220 enabled: null,
221 level: null,
222 dismissable: null,
223 message: null
224 },
225 search: {
226 remoteUri: {
227 users: null,
228 anonymous: null
229 },
230 searchIndex: {
231 enabled: null,
232 url: this.customConfigValidatorsService.SEARCH_INDEX_URL,
233 disableLocalSearch: null,
234 isDefaultSearch: null
235 }
236 }
237 }
238
239 const defaultValues = {
240 transcoding: {
241 resolutions: {}
242 }
243 }
244 for (const resolution of this.resolutions) {
245 defaultValues.transcoding.resolutions[resolution.id] = 'false'
246 formGroupData.transcoding.resolutions[resolution.id] = null
247 }
248
249 this.buildForm(formGroupData)
250 this.loadForm()
251 this.checkTranscodingFields()
252 }
253
254 ngAfterViewChecked () {
255 if (!this.initDone) {
256 this.initDone = true
257 this.gotoAnchor()
258 }
259 }
260
261 isTranscodingEnabled () {
262 return this.form.value['transcoding']['enabled'] === true
263 }
264
265 isSignupEnabled () {
266 return this.form.value['signup']['enabled'] === true
267 }
268
269 isSearchIndexEnabled () {
270 return this.form.value['search']['searchIndex']['enabled'] === true
271 }
272
273 isAutoFollowIndexEnabled () {
274 return this.form.value['followings']['instance']['autoFollowIndex']['enabled'] === true
275 }
276
277 async formValidated () {
278 this.configService.updateCustomConfig(this.form.getRawValue())
279 .subscribe(
280 res => {
281 this.customConfig = res
282
283 // Reload general configuration
284 this.serverService.resetConfig()
285
286 this.updateForm()
287
288 this.notifier.success(this.i18n('Configuration updated.'))
289 },
290
291 err => this.notifier.error(err.message)
292 )
293 }
294
295 getSelectedLanguageLabel () {
296 return this.i18n('{{\'{0} languages selected')
297 }
298
299 getDefaultLanguageLabel () {
300 return this.i18n('No language')
301 }
302
303 getSelectedCategoryLabel () {
304 return this.i18n('{{\'{0} categories selected')
305 }
306
307 getDefaultCategoryLabel () {
308 return this.i18n('No category')
309 }
310
311 gotoAnchor () {
312 const hashToNav = {
313 'customizations': 'advanced-configuration'
314 }
315 const hash = window.location.hash.replace('#', '')
316
317 if (hash && Object.keys(hashToNav).includes(hash)) {
318 this.nav.select(hashToNav[hash])
319 setTimeout(() => this.viewportScroller.scrollToAnchor(hash), 100)
320 }
321 }
322
323 private updateForm () {
324 this.form.patchValue(this.customConfig)
325 }
326
327 private loadForm () {
328 forkJoin([
329 this.configService.getCustomConfig(),
330 this.serverService.getVideoLanguages(),
331 this.serverService.getVideoCategories()
332 ]).subscribe(
333 ([ config, languages, categories ]) => {
334 this.customConfig = config
335
336 this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
337 this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
338
339 this.updateForm()
340 // Force form validation
341 this.forceCheck()
342 },
343
344 err => this.notifier.error(err.message)
345 )
346 }
347
348 private checkTranscodingFields () {
349 const hlsControl = this.form.get('transcoding.hls.enabled')
350 const webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
351
352 webtorrentControl.valueChanges
353 .subscribe(newValue => {
354 if (newValue === false && !hlsControl.disabled) {
355 hlsControl.disable()
356 }
357
358 if (newValue === true && !hlsControl.enabled) {
359 hlsControl.enable()
360 }
361 })
362
363 hlsControl.valueChanges
364 .subscribe(newValue => {
365 if (newValue === false && !webtorrentControl.disabled) {
366 webtorrentControl.disable()
367 }
368
369 if (newValue === true && !webtorrentControl.enabled) {
370 webtorrentControl.enable()
371 }
372 })
373 }
374 }