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