edit-custom-config.component.ts 9.34 KB
Newer Older
Chocobozzz's avatar
Chocobozzz committed
1

Chocobozzz's avatar
Chocobozzz committed
2
import omit from 'lodash-es/omit'
3
4
import { forkJoin } from 'rxjs'
import { SelectOptionsItem } from 'src/types/select-options-item.model'
Chocobozzz's avatar
Chocobozzz committed
5
import { Component, OnInit } from '@angular/core'
6
import { ActivatedRoute, Router } from '@angular/router'
Chocobozzz's avatar
Chocobozzz committed
7
8
9
import { ConfigService } from '@app/+admin/config/shared/config.service'
import { Notifier } from '@app/core'
import { ServerService } from '@app/core/server/server.service'
Chocobozzz's avatar
Chocobozzz committed
10
import {
11
12
13
  ADMIN_EMAIL_VALIDATOR,
  CACHE_CAPTIONS_SIZE_VALIDATOR,
  CACHE_PREVIEWS_SIZE_VALIDATOR,
14
  CONCURRENCY_VALIDATOR,
15
16
17
  INDEX_URL_VALIDATOR,
  INSTANCE_NAME_VALIDATOR,
  INSTANCE_SHORT_DESCRIPTION_VALIDATOR,
18
19
20
  MAX_INSTANCE_LIVES_VALIDATOR,
  MAX_LIVE_DURATION_VALIDATOR,
  MAX_USER_LIVES_VALIDATOR,
21
22
23
  SEARCH_INDEX_URL_VALIDATOR,
  SERVICES_TWITTER_USERNAME_VALIDATOR,
  SIGNUP_LIMIT_VALIDATOR,
24
  SIGNUP_MINIMUM_AGE_VALIDATOR,
25
26
27
  TRANSCODING_THREADS_VALIDATOR
} from '@app/shared/form-validators/custom-config-validators'
import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators'
Chocobozzz's avatar
Chocobozzz committed
28
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
Chocobozzz's avatar
Chocobozzz committed
29
import { CustomPageService } from '@app/shared/shared-main/custom-page'
Chocobozzz's avatar
Chocobozzz committed
30
import { CustomConfig, CustomPage, HTMLServerConfig } from '@shared/models'
Chocobozzz's avatar
Chocobozzz committed
31
import { EditConfigurationService } from './edit-configuration.service'
32

Chocobozzz's avatar
Chocobozzz committed
33
34
35
36
type ComponentCustomConfig = CustomConfig & {
  instanceCustomHomepage: CustomPage
}

37
38
39
40
41
@Component({
  selector: 'my-edit-custom-config',
  templateUrl: './edit-custom-config.component.html',
  styleUrls: [ './edit-custom-config.component.scss' ]
})
Chocobozzz's avatar
Chocobozzz committed
42
43
export class EditCustomConfigComponent extends FormReactive implements OnInit {
  activeNav: string
44

Chocobozzz's avatar
Chocobozzz committed
45
  customConfig: ComponentCustomConfig
Chocobozzz's avatar
Chocobozzz committed
46
  serverConfig: HTMLServerConfig
47

Chocobozzz's avatar
Chocobozzz committed
48
49
  homepage: CustomPage

Chocobozzz's avatar
Chocobozzz committed
50
51
  languageItems: SelectOptionsItem[] = []
  categoryItems: SelectOptionsItem[] = []
Chocobozzz's avatar
Chocobozzz committed
52

53
  constructor (
54
55
    private router: Router,
    private route: ActivatedRoute,
Chocobozzz's avatar
Chocobozzz committed
56
    protected formValidatorService: FormValidatorService,
Chocobozzz's avatar
Chocobozzz committed
57
    private notifier: Notifier,
58
    private configService: ConfigService,
Chocobozzz's avatar
Chocobozzz committed
59
    private customPage: CustomPageService,
Chocobozzz's avatar
Chocobozzz committed
60
61
    private serverService: ServerService,
    private editConfigurationService: EditConfigurationService
62
63
64
65
  ) {
    super()
  }

Chocobozzz's avatar
Chocobozzz committed
66
  ngOnInit () {
Chocobozzz's avatar
Chocobozzz committed
67
    this.serverConfig = this.serverService.getHTMLConfig()
Chocobozzz's avatar
Chocobozzz committed
68

Chocobozzz's avatar
Chocobozzz committed
69
    const formGroupData: { [key in keyof ComponentCustomConfig ]: any } = {
70
      instance: {
71
72
        name: INSTANCE_NAME_VALIDATOR,
        shortDescription: INSTANCE_SHORT_DESCRIPTION_VALIDATOR,
73
        description: null,
Chocobozzz's avatar
Chocobozzz committed
74

75
        isNSFW: false,
76
        defaultNSFWPolicy: null,
Chocobozzz's avatar
Chocobozzz committed
77
78
79

        terms: null,
        codeOfConduct: null,
Chocobozzz's avatar
Chocobozzz committed
80
81

        creationReason: null,
Chocobozzz's avatar
Chocobozzz committed
82
83
84
85
86
        moderationInformation: null,
        administrator: null,
        maintenanceLifetime: null,
        businessModel: null,

87
88
        hardwareInformation: null,

Chocobozzz's avatar
Chocobozzz committed
89
90
91
92
93
        categories: null,
        languages: null,

        defaultClientRoute: null,

94
95
96
97
98
        customizations: {
          javascript: null,
          css: null
        }
      },
Chocobozzz's avatar
Chocobozzz committed
99
100
101
      theme: {
        default: null
      },
102
103
      services: {
        twitter: {
104
          username: SERVICES_TWITTER_USERNAME_VALIDATOR,
105
106
107
108
109
          whitelisted: null
        }
      },
      cache: {
        previews: {
110
          size: CACHE_PREVIEWS_SIZE_VALIDATOR
111
112
        },
        captions: {
113
          size: CACHE_CAPTIONS_SIZE_VALIDATOR
114
115
116
        },
        torrents: {
          size: CACHE_CAPTIONS_SIZE_VALIDATOR
117
118
119
120
        }
      },
      signup: {
        enabled: null,
121
        limit: SIGNUP_LIMIT_VALIDATOR,
122
123
        requiresEmailVerification: null,
        minimumAge: SIGNUP_MINIMUM_AGE_VALIDATOR
124
125
126
      },
      import: {
        videos: {
127
          concurrency: CONCURRENCY_VALIDATOR,
128
129
130
131
132
133
134
135
          http: {
            enabled: null
          },
          torrent: {
            enabled: null
          }
        }
      },
136
137
138
139
140
141
142
143
      trending: {
        videos: {
          algorithms: {
            enabled: null,
            default: null
          }
        }
      },
144
      admin: {
145
        email: ADMIN_EMAIL_VALIDATOR
146
147
148
149
150
      },
      contactForm: {
        enabled: null
      },
      user: {
151
152
        videoQuota: USER_VIDEO_QUOTA_VALIDATOR,
        videoQuotaDaily: USER_VIDEO_QUOTA_DAILY_VALIDATOR
153
154
155
      },
      transcoding: {
        enabled: null,
156
        threads: TRANSCODING_THREADS_VALIDATOR,
157
        allowAdditionalExtensions: null,
Chocobozzz's avatar
Chocobozzz committed
158
        allowAudioFiles: null,
159
        profile: null,
160
        concurrency: CONCURRENCY_VALIDATOR,
161
162
163
        resolutions: {},
        hls: {
          enabled: null
164
165
166
        },
        webtorrent: {
          enabled: null
167
        }
168
      },
169
170
171
      live: {
        enabled: null,

172
173
174
        maxDuration: MAX_LIVE_DURATION_VALIDATOR,
        maxInstanceLives: MAX_INSTANCE_LIVES_VALIDATOR,
        maxUserLives: MAX_USER_LIVES_VALIDATOR,
Chocobozzz's avatar
Chocobozzz committed
175
176
        allowReplay: null,

177
178
179
        transcoding: {
          enabled: null,
          threads: TRANSCODING_THREADS_VALIDATOR,
180
          profile: null,
181
182
183
          resolutions: {}
        }
      },
184
185
186
187
188
189
      autoBlacklist: {
        videos: {
          ofUsers: {
            enabled: null
          }
        }
190
191
192
193
194
195
      },
      followers: {
        instance: {
          enabled: null,
          manualApproval: null
        }
Chocobozzz's avatar
Chocobozzz committed
196
197
198
199
200
201
202
203
      },
      followings: {
        instance: {
          autoFollowBack: {
            enabled: null
          },
          autoFollowIndex: {
            enabled: null,
204
            indexUrl: INDEX_URL_VALIDATOR
Chocobozzz's avatar
Chocobozzz committed
205
206
          }
        }
Chocobozzz's avatar
Chocobozzz committed
207
208
209
210
211
212
      },
      broadcastMessage: {
        enabled: null,
        level: null,
        dismissable: null,
        message: null
Chocobozzz's avatar
Chocobozzz committed
213
214
215
216
217
218
219
220
      },
      search: {
        remoteUri: {
          users: null,
          anonymous: null
        },
        searchIndex: {
          enabled: null,
221
          url: SEARCH_INDEX_URL_VALIDATOR,
Chocobozzz's avatar
Chocobozzz committed
222
223
224
          disableLocalSearch: null,
          isDefaultSearch: null
        }
Chocobozzz's avatar
Chocobozzz committed
225
226
227
228
      },

      instanceCustomHomepage: {
        content: null
229
      }
230
231
    }

232
233
234
    const defaultValues = {
      transcoding: {
        resolutions: {}
235
236
237
238
239
      },
      live: {
        transcoding: {
          resolutions: {}
        }
240
241
      }
    }
242

Chocobozzz's avatar
Chocobozzz committed
243
    for (const resolution of this.editConfigurationService.getVODResolutions()) {
244
245
      defaultValues.transcoding.resolutions[resolution.id] = 'false'
      formGroupData.transcoding.resolutions[resolution.id] = null
246
247
    }

Chocobozzz's avatar
Chocobozzz committed
248
    for (const resolution of this.editConfigurationService.getLiveResolutions()) {
249
250
251
252
      defaultValues.live.transcoding.resolutions[resolution.id] = 'false'
      formGroupData.live.transcoding.resolutions[resolution.id] = null
    }

Chocobozzz's avatar
Chocobozzz committed
253
    this.buildForm(formGroupData)
254

Chocobozzz's avatar
Chocobozzz committed
255
256
    if (this.route.snapshot.fragment) {
      this.onNavChange(this.route.snapshot.fragment)
257
    }
Chocobozzz's avatar
Chocobozzz committed
258

Chocobozzz's avatar
Chocobozzz committed
259
260
    this.loadConfigAndUpdateForm()
    this.loadCategoriesAndLanguages()
261
262
  }

263
  async formValidated () {
Chocobozzz's avatar
Chocobozzz committed
264
    const value: ComponentCustomConfig = this.form.getRawValue()
Chocobozzz's avatar
Chocobozzz committed
265

Chocobozzz's avatar
Chocobozzz committed
266
267
268
269
    forkJoin([
      this.configService.updateCustomConfig(omit(value, 'instanceCustomHomepage')),
      this.customPage.updateInstanceHomepage(value.instanceCustomHomepage.content)
    ])
270
      .subscribe(
Chocobozzz's avatar
Chocobozzz committed
271
272
273
274
275
276
        ([ resConfig ]) => {
          const instanceCustomHomepage = {
            content: value.instanceCustomHomepage.content
          }

          this.customConfig = { ...resConfig, instanceCustomHomepage }
277
278

          // Reload general configuration
Chocobozzz's avatar
Chocobozzz committed
279
          this.serverService.resetConfig()
Chocobozzz's avatar
Chocobozzz committed
280
            .subscribe(config => this.serverConfig = config)
281
282

          this.updateForm()
283

Chocobozzz's avatar
Chocobozzz committed
284
          this.notifier.success($localize`Configuration updated.`)
285
286
        },

Chocobozzz's avatar
Chocobozzz committed
287
        err => this.notifier.error(err.message)
288
289
290
      )
  }

Chocobozzz's avatar
Chocobozzz committed
291
292
293
294
295
296
297
  hasConsistentOptions () {
    if (this.hasLiveAllowReplayConsistentOptions()) return true

    return false
  }

  hasLiveAllowReplayConsistentOptions () {
Chocobozzz's avatar
Chocobozzz committed
298
299
300
301
302
    if (
      this.editConfigurationService.isTranscodingEnabled(this.form) === false &&
      this.editConfigurationService.isLiveEnabled(this.form) &&
      this.form.value['live']['allowReplay'] === true
    ) {
Chocobozzz's avatar
Chocobozzz committed
303
304
305
306
307
308
      return false
    }

    return true
  }

309
310
311
312
313
314
  onNavChange (newActiveNav: string) {
    this.activeNav = newActiveNav

    this.router.navigate([], { fragment: this.activeNav })
  }

Chocobozzz's avatar
Chocobozzz committed
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  grabAllErrors (errorObjectArg?: any) {
    const errorObject = errorObjectArg || this.formErrors

    let acc: string[] = []

    for (const key of Object.keys(errorObject)) {
      const value = errorObject[key]
      if (!value) continue

      if (typeof value === 'string') {
        acc.push(value)
      } else {
        acc = acc.concat(this.grabAllErrors(value))
      }
    }

    return acc
  }

334
  private updateForm () {
335
    this.form.patchValue(this.customConfig)
336
  }
337

Chocobozzz's avatar
Chocobozzz committed
338
  private loadConfigAndUpdateForm () {
Chocobozzz's avatar
Chocobozzz committed
339
340
341
342
343
344
    forkJoin([
      this.configService.getCustomConfig(),
      this.customPage.getInstanceHomepage()
    ])
      .subscribe(([ config, homepage ]) => {
        this.customConfig = { ...config, instanceCustomHomepage: homepage }
345
346
347
348
349
350
351
352
353
354

        this.updateForm()
        // Force form validation
        this.forceCheck()
      },

      err => this.notifier.error(err.message)
    )
  }

Chocobozzz's avatar
Chocobozzz committed
355
356
357
358
359
360
361
362
363
  private loadCategoriesAndLanguages () {
    forkJoin([
      this.serverService.getVideoLanguages(),
      this.serverService.getVideoCategories()
    ]).subscribe(
      ([ languages, categories ]) => {
        this.languageItems = languages.map(l => ({ label: l.label, id: l.id }))
        this.categoryItems = categories.map(l => ({ label: l.label, id: l.id + '' }))
      },
364

Chocobozzz's avatar
Chocobozzz committed
365
366
      err => this.notifier.error(err.message)
    )
367
  }
368
}