From fd206f0b2d7e5c8e00e2817266d90ec54f79e1da Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 17 Jan 2018 10:32:03 +0100 Subject: Add ability to update some configuration keys --- client/src/app/+admin/admin-routing.module.ts | 6 +- client/src/app/+admin/admin.component.html | 4 + client/src/app/+admin/admin.component.ts | 4 + client/src/app/+admin/admin.module.ts | 10 +- client/src/app/+admin/config/config.component.ts | 7 + client/src/app/+admin/config/config.routes.ts | 32 ++++ .../edit-custom-config.component.html | 97 ++++++++++++ .../edit-custom-config.component.scss | 31 ++++ .../edit-custom-config.component.ts | 174 +++++++++++++++++++++ .../app/+admin/config/edit-custom-config/index.ts | 1 + client/src/app/+admin/config/index.ts | 3 + .../src/app/+admin/config/shared/config.service.ts | 26 +++ .../account-details/account-details.component.html | 2 - .../account-details/account-details.component.ts | 5 +- client/src/app/menu/menu.component.html | 2 +- .../shared/forms/form-validators/custom-config.ts | 35 +++++ 16 files changed, 428 insertions(+), 11 deletions(-) create mode 100644 client/src/app/+admin/config/config.component.ts create mode 100644 client/src/app/+admin/config/config.routes.ts create mode 100644 client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html create mode 100644 client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss create mode 100644 client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts create mode 100644 client/src/app/+admin/config/edit-custom-config/index.ts create mode 100644 client/src/app/+admin/config/index.ts create mode 100644 client/src/app/+admin/config/shared/config.service.ts create mode 100644 client/src/app/shared/forms/form-validators/custom-config.ts (limited to 'client/src/app') diff --git a/client/src/app/+admin/admin-routing.module.ts b/client/src/app/+admin/admin-routing.module.ts index 7ef5c6105..0301d7601 100644 --- a/client/src/app/+admin/admin-routing.module.ts +++ b/client/src/app/+admin/admin-routing.module.ts @@ -1,14 +1,15 @@ import { NgModule } from '@angular/core' import { RouterModule, Routes } from '@angular/router' +import { ConfigRoutes } from '@app/+admin/config' import { MetaGuard } from '@ngx-meta/core' import { AdminComponent } from './admin.component' import { FollowsRoutes } from './follows' +import { JobsRoutes } from './jobs/job.routes' import { UsersRoutes } from './users' import { VideoAbusesRoutes } from './video-abuses' import { VideoBlacklistRoutes } from './video-blacklist' -import { JobsRoutes } from './jobs/job.routes' const adminRoutes: Routes = [ { @@ -26,7 +27,8 @@ const adminRoutes: Routes = [ ...UsersRoutes, ...VideoAbusesRoutes, ...VideoBlacklistRoutes, - ...JobsRoutes + ...JobsRoutes, + ...ConfigRoutes ] } ] diff --git a/client/src/app/+admin/admin.component.html b/client/src/app/+admin/admin.component.html index 0bf4c8aac..e4644498b 100644 --- a/client/src/app/+admin/admin.component.html +++ b/client/src/app/+admin/admin.component.html @@ -19,6 +19,10 @@ Jobs + + + Configuration +
diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts index 75cd50cc7..1a4dd6786 100644 --- a/client/src/app/+admin/admin.component.ts +++ b/client/src/app/+admin/admin.component.ts @@ -28,4 +28,8 @@ export class AdminComponent { hasJobsRight () { return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS) } + + hasConfigRight () { + return this.auth.getUser().hasRight(UserRight.MANAGE_CONFIGURATION) + } } diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index 74ceb25ef..1d9120490 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts @@ -1,4 +1,6 @@ import { NgModule } from '@angular/core' +import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config' +import { ConfigService } from '@app/+admin/config/shared/config.service' import { TabsModule } from 'ngx-bootstrap/tabs' import { DataTableModule } from 'primeng/components/datatable/datatable' import { SharedModule } from '../shared' @@ -41,7 +43,10 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl VideoAbuseListComponent, JobsComponent, - JobsListComponent + JobsListComponent, + + ConfigComponent, + EditCustomConfigComponent ], exports: [ @@ -51,7 +56,8 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl providers: [ FollowService, UserService, - JobService + JobService, + ConfigService ] }) export class AdminModule { } diff --git a/client/src/app/+admin/config/config.component.ts b/client/src/app/+admin/config/config.component.ts new file mode 100644 index 000000000..e0eb77278 --- /dev/null +++ b/client/src/app/+admin/config/config.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core' + +@Component({ + template: '' +}) +export class ConfigComponent { +} diff --git a/client/src/app/+admin/config/config.routes.ts b/client/src/app/+admin/config/config.routes.ts new file mode 100644 index 000000000..a46b0ddfd --- /dev/null +++ b/client/src/app/+admin/config/config.routes.ts @@ -0,0 +1,32 @@ +import { Routes } from '@angular/router' +import { EditCustomConfigComponent } from '@app/+admin/config/edit-custom-config' +import { UserRightGuard } from '@app/core' +import { UserRight } from '../../../../../shared/models/users' +import { ConfigComponent } from './config.component' + +export const ConfigRoutes: Routes = [ + { + path: 'config', + component: ConfigComponent, + canActivate: [ UserRightGuard ], + data: { + userRight: UserRight.MANAGE_CONFIGURATION + }, + children: [ + { + path: '', + redirectTo: 'edit-custom', + pathMatch: 'full' + }, + { + path: 'edit-custom', + component: EditCustomConfigComponent, + data: { + meta: { + title: 'Following list' + } + } + } + ] + } +] diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html new file mode 100644 index 000000000..c568a43b4 --- /dev/null +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html @@ -0,0 +1,97 @@ +
Update PeerTube configuration
+ +
+ +
Cache
+ +
+ + +
+ {{ formErrors.cachePreviewsSize }} +
+
+ +
Signup
+ +
+ + + + +
+ +
+ + +
+ {{ formErrors.signupLimit }} +
+
+ +
Administrator
+ +
+ + +
+ {{ formErrors.adminEmail }} +
+
+ +
Users
+ +
+ +
+ +
+
+ +
Transcoding
+ +
+ + + + +
+ + + +
+ +
+ +
+
+ +
+ + + +
+
+ + +
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss new file mode 100644 index 000000000..0195f44eb --- /dev/null +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss @@ -0,0 +1,31 @@ +@import '_variables'; +@import '_mixins'; + +input[type=text] { + @include peertube-input-text(340px); + display: block; +} + +input[type=checkbox] { + @include peertube-checkbox(1px); +} + +.peertube-select-container { + @include peertube-select-container(340px); +} + +input[type=submit] { + @include peertube-button; + @include orange-button; + + margin-top: 20px; +} + +.inner-form-title { + text-transform: uppercase; + color: $orange-color; + font-weight: $font-bold; + font-size: 13px; + margin-top: 30px; + margin-bottom: 10px; +} diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts new file mode 100644 index 000000000..1b3522786 --- /dev/null +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts @@ -0,0 +1,174 @@ +import { Component, OnInit } from '@angular/core' +import { FormBuilder, FormGroup } from '@angular/forms' +import { Router } from '@angular/router' +import { ConfigService } from '@app/+admin/config/shared/config.service' +import { ServerService } from '@app/core/server/server.service' +import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared' +import { ADMIN_EMAIL, CACHE_PREVIEWS_SIZE, SIGNUP_LIMIT, TRANSCODING_THREADS } from '@app/shared/forms/form-validators/custom-config' +import { NotificationsService } from 'angular2-notifications' +import { CustomConfig } from '../../../../../../shared/models/config/custom-config.model' + +@Component({ + selector: 'my-edit-custom-config', + templateUrl: './edit-custom-config.component.html', + styleUrls: [ './edit-custom-config.component.scss' ] +}) +export class EditCustomConfigComponent extends FormReactive implements OnInit { + customConfig: CustomConfig + resolutions = [ '240p', '360p', '480p', '720p', '1080p' ] + + videoQuotaOptions = [ + { value: -1, label: 'Unlimited' }, + { value: 0, label: '0' }, + { value: 100 * 1024 * 1024, label: '100MB' }, + { value: 500 * 1024 * 1024, label: '500MB' }, + { value: 1024 * 1024 * 1024, label: '1GB' }, + { value: 5 * 1024 * 1024 * 1024, label: '5GB' }, + { value: 20 * 1024 * 1024 * 1024, label: '20GB' }, + { value: 50 * 1024 * 1024 * 1024, label: '50GB' } + ] + transcodingThreadOptions = [ + { value: 1, label: '1' }, + { value: 2, label: '2' }, + { value: 4, label: '4' }, + { value: 8, label: '8' } + ] + + form: FormGroup + formErrors = { + cachePreviewsSize: '', + signupLimit: '', + adminEmail: '', + userVideoQuota: '', + transcodingThreads: '' + } + validationMessages = { + cachePreviewsSize: CACHE_PREVIEWS_SIZE.MESSAGES, + signupLimit: SIGNUP_LIMIT.MESSAGES, + adminEmail: ADMIN_EMAIL.MESSAGES, + userVideoQuota: USER_VIDEO_QUOTA.MESSAGES + } + + constructor ( + private formBuilder: FormBuilder, + private router: Router, + private notificationsService: NotificationsService, + private configService: ConfigService, + private serverService: ServerService + ) { + super() + } + + getResolutionKey (resolution: string) { + return 'transcodingResolution' + resolution + } + + buildForm () { + const formGroupData = { + cachePreviewsSize: [ '', CACHE_PREVIEWS_SIZE.VALIDATORS ], + signupEnabled: [ ], + signupLimit: [ '', SIGNUP_LIMIT.VALIDATORS ], + adminEmail: [ '', ADMIN_EMAIL.VALIDATORS ], + userVideoQuota: [ '', USER_VIDEO_QUOTA.VALIDATORS ], + transcodingThreads: [ '', TRANSCODING_THREADS.VALIDATORS ], + transcodingEnabled: [ ] + } + + for (const resolution of this.resolutions) { + const key = this.getResolutionKey(resolution) + formGroupData[key] = [ false ] + } + + this.form = this.formBuilder.group(formGroupData) + + this.form.valueChanges.subscribe(data => this.onValueChanged(data)) + } + + ngOnInit () { + this.buildForm() + + this.configService.getCustomConfig() + .subscribe( + res => { + this.customConfig = res + + this.updateForm() + }, + + err => this.notificationsService.error('Error', err.message) + ) + } + + isTranscodingEnabled () { + return this.form.value['transcodingEnabled'] === true + } + + isSignupEnabled () { + return this.form.value['signupEnabled'] === true + } + + formValidated () { + const data = { + cache: { + previews: { + size: this.form.value['cachePreviewsSize'] + } + }, + signup: { + enabled: this.form.value['signupEnabled'], + limit: this.form.value['signupLimit'] + }, + admin: { + email: this.form.value['adminEmail'] + }, + user: { + videoQuota: this.form.value['userVideoQuota'] + }, + transcoding: { + enabled: this.form.value['transcodingEnabled'], + threads: this.form.value['transcodingThreads'], + resolutions: { + '240p': this.form.value[this.getResolutionKey('240p')], + '360p': this.form.value[this.getResolutionKey('360p')], + '480p': this.form.value[this.getResolutionKey('480p')], + '720p': this.form.value[this.getResolutionKey('720p')], + '1080p': this.form.value[this.getResolutionKey('1080p')] + } + } + } + + this.configService.updateCustomConfig(data) + .subscribe( + res => { + this.customConfig = res + + // Reload general configuration + this.serverService.loadConfig() + + this.updateForm() + }, + + err => this.notificationsService.error('Error', err.message) + ) + } + + private updateForm () { + const data = { + cachePreviewsSize: this.customConfig.cache.previews.size, + signupEnabled: this.customConfig.signup.enabled, + signupLimit: this.customConfig.signup.limit, + adminEmail: this.customConfig.admin.email, + userVideoQuota: this.customConfig.user.videoQuota, + transcodingThreads: this.customConfig.transcoding.threads, + transcodingEnabled: this.customConfig.transcoding.enabled + } + + for (const resolution of this.resolutions) { + const key = this.getResolutionKey(resolution) + data[key] = this.customConfig.transcoding.resolutions[resolution] + } + + this.form.patchValue(data) + } + +} diff --git a/client/src/app/+admin/config/edit-custom-config/index.ts b/client/src/app/+admin/config/edit-custom-config/index.ts new file mode 100644 index 000000000..1ec12631f --- /dev/null +++ b/client/src/app/+admin/config/edit-custom-config/index.ts @@ -0,0 +1 @@ +export * from './edit-custom-config.component' diff --git a/client/src/app/+admin/config/index.ts b/client/src/app/+admin/config/index.ts new file mode 100644 index 000000000..b47ebf8db --- /dev/null +++ b/client/src/app/+admin/config/index.ts @@ -0,0 +1,3 @@ +export * from './edit-custom-config' +export * from './config.component' +export * from './config.routes' diff --git a/client/src/app/+admin/config/shared/config.service.ts b/client/src/app/+admin/config/shared/config.service.ts new file mode 100644 index 000000000..13f1f6cd2 --- /dev/null +++ b/client/src/app/+admin/config/shared/config.service.ts @@ -0,0 +1,26 @@ +import { HttpClient } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { CustomConfig } from '../../../../../../shared/models/config/custom-config.model' +import { environment } from '../../../../environments/environment' +import { RestExtractor, RestService } from '../../../shared' + +@Injectable() +export class ConfigService { + private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/config' + + constructor ( + private authHttp: HttpClient, + private restService: RestService, + private restExtractor: RestExtractor + ) {} + + getCustomConfig () { + return this.authHttp.get(ConfigService.BASE_APPLICATION_URL + '/custom') + .catch(res => this.restExtractor.handleError(res)) + } + + updateCustomConfig (data: CustomConfig) { + return this.authHttp.put(ConfigService.BASE_APPLICATION_URL + '/custom', data) + .catch(res => this.restExtractor.handleError(res)) + } +} diff --git a/client/src/app/account/account-settings/account-details/account-details.component.html b/client/src/app/account/account-settings/account-details/account-details.component.html index c8e1e73b0..8f1475a4d 100644 --- a/client/src/app/account/account-settings/account-details/account-details.component.html +++ b/client/src/app/account/account-settings/account-details/account-details.component.html @@ -1,5 +1,3 @@ -
{{ error }}
-
{ this.notificationsService.success('Success', 'Information updated.') @@ -58,7 +55,7 @@ export class AccountDetailsComponent extends FormReactive implements OnInit { this.authService.refreshUserInformation() }, - err => this.error = err.message + err => this.notificationsService.error('Error', err.message) ) } } diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html index d138d2ba7..94f82e352 100644 --- a/client/src/app/menu/menu.component.html +++ b/client/src/app/menu/menu.component.html @@ -14,7 +14,7 @@