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