Add ability to change the homepage
[oweals/peertube.git] / client / src / app / +admin / config / edit-custom-config / edit-custom-config.component.ts
1 import { Component, OnInit } from '@angular/core'
2 import { FormBuilder, FormGroup } from '@angular/forms'
3 import { Router } from '@angular/router'
4 import { ConfigService } from '@app/+admin/config/shared/config.service'
5 import { ConfirmService } from '@app/core'
6 import { ServerService } from '@app/core/server/server.service'
7 import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared'
8 import {
9   ADMIN_EMAIL,
10   CACHE_PREVIEWS_SIZE,
11   INSTANCE_NAME,
12   SIGNUP_LIMIT,
13   TRANSCODING_THREADS
14 } from '@app/shared/forms/form-validators/custom-config'
15 import { NotificationsService } from 'angular2-notifications'
16 import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
17
18 @Component({
19   selector: 'my-edit-custom-config',
20   templateUrl: './edit-custom-config.component.html',
21   styleUrls: [ './edit-custom-config.component.scss' ]
22 })
23 export class EditCustomConfigComponent extends FormReactive implements OnInit {
24   customConfig: CustomConfig
25   resolutions = [ '240p', '360p', '480p', '720p', '1080p' ]
26
27   videoQuotaOptions = [
28     { value: -1, label: 'Unlimited' },
29     { value: 0, label: '0' },
30     { value: 100 * 1024 * 1024, label: '100MB' },
31     { value: 500 * 1024 * 1024, label: '500MB' },
32     { value: 1024 * 1024 * 1024, label: '1GB' },
33     { value: 5 * 1024 * 1024 * 1024, label: '5GB' },
34     { value: 20 * 1024 * 1024 * 1024, label: '20GB' },
35     { value: 50 * 1024 * 1024 * 1024, label: '50GB' }
36   ]
37   transcodingThreadOptions = [
38     { value: 1, label: '1' },
39     { value: 2, label: '2' },
40     { value: 4, label: '4' },
41     { value: 8, label: '8' }
42   ]
43
44   form: FormGroup
45   formErrors = {
46     instanceName: '',
47     instanceDescription: '',
48     instanceTerms: '',
49     instanceDefaultClientRoute: '',
50     cachePreviewsSize: '',
51     signupLimit: '',
52     adminEmail: '',
53     userVideoQuota: '',
54     transcodingThreads: '',
55     customizationJavascript: '',
56     customizationCSS: ''
57   }
58   validationMessages = {
59     instanceName: INSTANCE_NAME.MESSAGES,
60     cachePreviewsSize: CACHE_PREVIEWS_SIZE.MESSAGES,
61     signupLimit: SIGNUP_LIMIT.MESSAGES,
62     adminEmail: ADMIN_EMAIL.MESSAGES,
63     userVideoQuota: USER_VIDEO_QUOTA.MESSAGES
64   }
65
66   private oldCustomJavascript: string
67   private oldCustomCSS: string
68
69   constructor (
70     private formBuilder: FormBuilder,
71     private router: Router,
72     private notificationsService: NotificationsService,
73     private configService: ConfigService,
74     private serverService: ServerService,
75     private confirmService: ConfirmService
76   ) {
77     super()
78   }
79
80   getResolutionKey (resolution: string) {
81     return 'transcodingResolution' + resolution
82   }
83
84   buildForm () {
85     const formGroupData = {
86       instanceName: [ '', INSTANCE_NAME.VALIDATORS ],
87       instanceDescription: [ '' ],
88       instanceTerms: [ '' ],
89       instanceDefaultClientRoute: [ '' ],
90       cachePreviewsSize: [ '', CACHE_PREVIEWS_SIZE.VALIDATORS ],
91       signupEnabled: [ ],
92       signupLimit: [ '', SIGNUP_LIMIT.VALIDATORS ],
93       adminEmail: [ '', ADMIN_EMAIL.VALIDATORS ],
94       userVideoQuota: [ '', USER_VIDEO_QUOTA.VALIDATORS ],
95       transcodingThreads: [ '', TRANSCODING_THREADS.VALIDATORS ],
96       transcodingEnabled: [ ],
97       customizationJavascript: [ '' ],
98       customizationCSS: [ '' ]
99     }
100
101     for (const resolution of this.resolutions) {
102       const key = this.getResolutionKey(resolution)
103       formGroupData[key] = [ false ]
104     }
105
106     this.form = this.formBuilder.group(formGroupData)
107
108     this.form.valueChanges.subscribe(data => this.onValueChanged(data))
109   }
110
111   ngOnInit () {
112     this.buildForm()
113
114     this.configService.getCustomConfig()
115       .subscribe(
116         res => {
117           this.customConfig = res
118
119           this.oldCustomCSS = this.customConfig.instance.customizations.css
120           this.oldCustomJavascript = this.customConfig.instance.customizations.javascript
121
122           this.updateForm()
123         },
124
125         err => this.notificationsService.error('Error', err.message)
126       )
127   }
128
129   isTranscodingEnabled () {
130     return this.form.value['transcodingEnabled'] === true
131   }
132
133   isSignupEnabled () {
134     return this.form.value['signupEnabled'] === true
135   }
136
137   async formValidated () {
138     const newCustomizationJavascript = this.form.value['customizationJavascript']
139     const newCustomizationCSS = this.form.value['customizationCSS']
140
141     const customizations = []
142     if (newCustomizationJavascript && newCustomizationJavascript !== this.oldCustomJavascript) customizations.push('JavaScript')
143     if (newCustomizationCSS && newCustomizationCSS !== this.oldCustomCSS) customizations.push('CSS')
144
145     if (customizations.length !== 0) {
146       const customizationsText = customizations.join('/')
147
148       const message = `You set custom ${customizationsText}. ` +
149         'This could lead to security issues or bugs if you do not understand it. ' +
150         'Are you sure you want to update the configuration?'
151       const label = `Please type "I understand the ${customizationsText} I set" to confirm.`
152       const expectedInputValue = `I understand the ${customizationsText} I set`
153
154       const confirmRes = await this.confirmService.confirmWithInput(message, label, expectedInputValue)
155       if (confirmRes === false) return
156     }
157
158     const data: CustomConfig = {
159       instance: {
160         name: this.form.value['instanceName'],
161         description: this.form.value['instanceDescription'],
162         terms: this.form.value['instanceTerms'],
163         defaultClientRoute: this.form.value['instanceDefaultClientRoute'],
164         customizations: {
165           javascript: this.form.value['customizationJavascript'],
166           css: this.form.value['customizationCSS']
167         }
168       },
169       cache: {
170         previews: {
171           size: this.form.value['cachePreviewsSize']
172         }
173       },
174       signup: {
175         enabled: this.form.value['signupEnabled'],
176         limit: this.form.value['signupLimit']
177       },
178       admin: {
179         email: this.form.value['adminEmail']
180       },
181       user: {
182         videoQuota: this.form.value['userVideoQuota']
183       },
184       transcoding: {
185         enabled: this.form.value['transcodingEnabled'],
186         threads: this.form.value['transcodingThreads'],
187         resolutions: {
188           '240p': this.form.value[this.getResolutionKey('240p')],
189           '360p': this.form.value[this.getResolutionKey('360p')],
190           '480p': this.form.value[this.getResolutionKey('480p')],
191           '720p': this.form.value[this.getResolutionKey('720p')],
192           '1080p': this.form.value[this.getResolutionKey('1080p')]
193         }
194       }
195     }
196
197     this.configService.updateCustomConfig(data)
198       .subscribe(
199         res => {
200           this.customConfig = res
201
202           // Reload general configuration
203           this.serverService.loadConfig()
204
205           this.updateForm()
206
207           this.notificationsService.success('Success', 'Configuration updated.')
208         },
209
210         err => this.notificationsService.error('Error', err.message)
211       )
212   }
213
214   private updateForm () {
215     const data = {
216       instanceName: this.customConfig.instance.name,
217       instanceDescription: this.customConfig.instance.description,
218       instanceTerms: this.customConfig.instance.terms,
219       instanceDefaultClientRoute: this.customConfig.instance.defaultClientRoute,
220       cachePreviewsSize: this.customConfig.cache.previews.size,
221       signupEnabled: this.customConfig.signup.enabled,
222       signupLimit: this.customConfig.signup.limit,
223       adminEmail: this.customConfig.admin.email,
224       userVideoQuota: this.customConfig.user.videoQuota,
225       transcodingThreads: this.customConfig.transcoding.threads,
226       transcodingEnabled: this.customConfig.transcoding.enabled,
227       customizationJavascript: this.customConfig.instance.customizations.javascript,
228       customizationCSS: this.customConfig.instance.customizations.css
229     }
230
231     for (const resolution of this.resolutions) {
232       const key = this.getResolutionKey(resolution)
233       data[key] = this.customConfig.transcoding.resolutions[resolution]
234     }
235
236     this.form.patchValue(data)
237   }
238
239 }