]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
change fixtures to reflect output size of jimp
[github/Chocobozzz/PeerTube.git] / client / src / app / +admin / config / edit-custom-config / edit-custom-config.component.ts
CommitLineData
45c6bcf3 1import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core'
fd206f0b
C
2import { ConfigService } from '@app/+admin/config/shared/config.service'
3import { ServerService } from '@app/core/server/server.service'
e309822b 4import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } from '@app/shared'
f8b2c1b4 5import { Notifier } from '@app/core'
09cababd 6import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
b1d40cff 7import { I18n } from '@ngx-translate/i18n-polyfill'
0dc64777 8import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
ccc00cb2
C
9import { SelectItem } from 'primeng/api'
10import { forkJoin } from 'rxjs'
ba430d75 11import { ServerConfig } from '@shared/models'
45e0d669 12import { ViewportScroller } from '@angular/common'
45c6bcf3 13import { NgbNav } from '@ng-bootstrap/ng-bootstrap'
fd206f0b
C
14
15@Component({
16 selector: 'my-edit-custom-config',
17 templateUrl: './edit-custom-config.component.html',
18 styleUrls: [ './edit-custom-config.component.scss' ]
19})
45e0d669 20export class EditCustomConfigComponent extends FormReactive implements OnInit, AfterViewChecked {
45c6bcf3
C
21 // FIXME: use built-in router
22 @ViewChild('nav') nav: NgbNav
45e0d669
RK
23
24 initDone = false
bee0abff 25 customConfig: CustomConfig
bee0abff 26
46db9430 27 resolutions: { id: string, label: string, description?: string }[] = []
3827c3b3 28 transcodingThreadOptions: { label: string, value: number }[] = []
fd206f0b 29
ccc00cb2
C
30 languageItems: SelectItem[] = []
31 categoryItems: SelectItem[] = []
32
ba430d75
C
33 private serverConfig: ServerConfig
34
fd206f0b 35 constructor (
45e0d669 36 private viewportScroller: ViewportScroller,
d18d6478 37 protected formValidatorService: FormValidatorService,
e309822b
C
38 private customConfigValidatorsService: CustomConfigValidatorsService,
39 private userValidatorsService: UserValidatorsService,
f8b2c1b4 40 private notifier: Notifier,
fd206f0b 41 private configService: ConfigService,
1f30a185 42 private serverService: ServerService,
b1d40cff 43 private i18n: I18n
fd206f0b
C
44 ) {
45 super()
3827c3b3
C
46
47 this.resolutions = [
2fa9c40e 48 {
5c7d6508 49 id: '0p',
46db9430 50 label: this.i18n('Audio-only'),
6a07a058 51 description: this.i18n('A <code>.mp4</code> that keeps the original audio track, with no video')
5c7d6508 52 },
00aa1f0d
C
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 }
3827c3b3
C
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 ]
fd206f0b
C
86 }
87
41a676db 88 get videoQuotaOptions () {
3827c3b3 89 return this.configService.videoQuotaOptions
41a676db
C
90 }
91
92 get videoQuotaDailyOptions () {
3827c3b3 93 return this.configService.videoQuotaDailyOptions
41a676db
C
94 }
95
7cd4d2ba 96 get availableThemes () {
ba430d75 97 return this.serverConfig.theme.registered
ffb321be 98 .map(t => t.name)
7cd4d2ba
C
99 }
100
fd206f0b 101 getResolutionKey (resolution: string) {
3866f1a0 102 return 'transcoding.resolutions.' + resolution
fd206f0b
C
103 }
104
d18d6478 105 ngOnInit () {
ba430d75
C
106 this.serverConfig = this.serverService.getTmpConfig()
107 this.serverService.getConfig()
108 .subscribe(config => this.serverConfig = config)
109
3866f1a0
C
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,
ccc00cb2 115
f8802489 116 isNSFW: false,
3866f1a0 117 defaultNSFWPolicy: null,
ccc00cb2
C
118
119 terms: null,
120 codeOfConduct: null,
8ae03c37
C
121
122 creationReason: null,
ccc00cb2
C
123 moderationInformation: null,
124 administrator: null,
125 maintenanceLifetime: null,
126 businessModel: null,
127
be04c6fd
C
128 hardwareInformation: null,
129
ccc00cb2
C
130 categories: null,
131 languages: null,
132
133 defaultClientRoute: null,
134
3866f1a0
C
135 customizations: {
136 javascript: null,
137 css: null
138 }
139 },
7cd4d2ba
C
140 theme: {
141 default: null
142 },
3866f1a0
C
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,
536598cf 186 allowAudioFiles: null,
5d9e4eaa
C
187 resolutions: {},
188 hls: {
189 enabled: null
5a71acd2
C
190 },
191 webtorrent: {
192 enabled: null
5d9e4eaa 193 }
7ccddd7b
JM
194 },
195 autoBlacklist: {
196 videos: {
197 ofUsers: {
198 enabled: null
199 }
200 }
0dc64777
C
201 },
202 followers: {
203 instance: {
204 enabled: null,
205 manualApproval: null
206 }
e1b49ee5
C
207 },
208 followings: {
209 instance: {
210 autoFollowBack: {
211 enabled: null
212 },
213 autoFollowIndex: {
214 enabled: null,
215 indexUrl: this.customConfigValidatorsService.INDEX_URL
216 }
217 }
72c33e71
C
218 },
219 broadcastMessage: {
220 enabled: null,
221 level: null,
222 dismissable: null,
223 message: null
3866f1a0 224 }
fd206f0b
C
225 }
226
3866f1a0
C
227 const defaultValues = {
228 transcoding: {
229 resolutions: {}
230 }
231 }
fd206f0b 232 for (const resolution of this.resolutions) {
00aa1f0d
C
233 defaultValues.transcoding.resolutions[resolution.id] = 'false'
234 formGroupData.transcoding.resolutions[resolution.id] = null
fd206f0b
C
235 }
236
d18d6478 237 this.buildForm(formGroupData)
04cda1d7
C
238 this.loadForm()
239 this.checkTranscodingFields()
fd206f0b
C
240 }
241
45e0d669
RK
242 ngAfterViewChecked () {
243 if (!this.initDone) {
244 this.initDone = true
245 this.gotoAnchor()
246 }
247 }
248
fd206f0b 249 isTranscodingEnabled () {
3866f1a0 250 return this.form.value['transcoding']['enabled'] === true
fd206f0b
C
251 }
252
253 isSignupEnabled () {
3866f1a0 254 return this.form.value['signup']['enabled'] === true
fd206f0b
C
255 }
256
4ee6a8b1
C
257 isAutoFollowIndexEnabled () {
258 return this.form.value['followings']['instance']['autoFollowIndex']['enabled'] === true
259 }
260
1f30a185 261 async formValidated () {
04cda1d7 262 this.configService.updateCustomConfig(this.form.getRawValue())
fd206f0b
C
263 .subscribe(
264 res => {
265 this.customConfig = res
266
267 // Reload general configuration
ba430d75 268 this.serverService.resetConfig()
fd206f0b
C
269
270 this.updateForm()
66b16caf 271
f8b2c1b4 272 this.notifier.success(this.i18n('Configuration updated.'))
fd206f0b
C
273 },
274
f8b2c1b4 275 err => this.notifier.error(err.message)
fd206f0b
C
276 )
277 }
278
ccc00cb2
C
279 getSelectedLanguageLabel () {
280 return this.i18n('{{\'{0} languages selected')
281 }
282
283 getDefaultLanguageLabel () {
284 return this.i18n('No language')
285 }
286
287 getSelectedCategoryLabel () {
288 return this.i18n('{{\'{0} categories selected')
289 }
290
291 getDefaultCategoryLabel () {
292 return this.i18n('No category')
293 }
294
45e0d669 295 gotoAnchor () {
45c6bcf3 296 const hashToNav = {
45e0d669
RK
297 'customizations': 'advanced-configuration'
298 }
299 const hash = window.location.hash.replace('#', '')
300
45c6bcf3
C
301 if (hash && Object.keys(hashToNav).includes(hash)) {
302 this.nav.select(hashToNav[hash])
45e0d669
RK
303 setTimeout(() => this.viewportScroller.scrollToAnchor(hash), 100)
304 }
305 }
306
fd206f0b 307 private updateForm () {
3866f1a0 308 this.form.patchValue(this.customConfig)
fd206f0b 309 }
04cda1d7
C
310
311 private loadForm () {
312 forkJoin([
313 this.configService.getCustomConfig(),
314 this.serverService.getVideoLanguages(),
315 this.serverService.getVideoCategories()
316 ]).subscribe(
317 ([ config, languages, categories ]) => {
318 this.customConfig = config
319
320 this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
321 this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
322
323 this.updateForm()
324 // Force form validation
325 this.forceCheck()
326 },
327
328 err => this.notifier.error(err.message)
329 )
330 }
331
332 private checkTranscodingFields () {
333 const hlsControl = this.form.get('transcoding.hls.enabled')
334 const webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
335
336 webtorrentControl.valueChanges
337 .subscribe(newValue => {
338 if (newValue === false && !hlsControl.disabled) {
339 hlsControl.disable()
340 }
341
342 if (newValue === true && !hlsControl.enabled) {
343 hlsControl.enable()
344 }
345 })
346
347 hlsControl.valueChanges
348 .subscribe(newValue => {
349 if (newValue === false && !webtorrentControl.disabled) {
350 webtorrentControl.disable()
351 }
352
353 if (newValue === true && !webtorrentControl.enabled) {
354 webtorrentControl.enable()
355 }
356 })
357 }
fd206f0b 358}