From 40e87e9ecc54e3513fb586928330a7855eb192c6 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 12 Jul 2018 19:02:00 +0200 Subject: Implement captions/subtitles --- .../custom-config-validators.service.ts | 10 +++ .../src/app/shared/forms/form-validators/index.ts | 1 + .../video-captions-validators.service.ts | 27 ++++++++ client/src/app/shared/forms/index.ts | 1 + .../app/shared/forms/reactive-file.component.html | 14 ++++ .../app/shared/forms/reactive-file.component.scss | 24 +++++++ .../app/shared/forms/reactive-file.component.ts | 75 ++++++++++++++++++++++ 7 files changed, 152 insertions(+) create mode 100644 client/src/app/shared/forms/form-validators/video-captions-validators.service.ts create mode 100644 client/src/app/shared/forms/reactive-file.component.html create mode 100644 client/src/app/shared/forms/reactive-file.component.scss create mode 100644 client/src/app/shared/forms/reactive-file.component.ts (limited to 'client/src/app/shared/forms') diff --git a/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts b/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts index 1b36bbc6b..0c2489a9d 100644 --- a/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts +++ b/client/src/app/shared/forms/form-validators/custom-config-validators.service.ts @@ -9,6 +9,7 @@ export class CustomConfigValidatorsService { readonly INSTANCE_SHORT_DESCRIPTION: BuildFormValidator readonly SERVICES_TWITTER_USERNAME: BuildFormValidator readonly CACHE_PREVIEWS_SIZE: BuildFormValidator + readonly CACHE_CAPTIONS_SIZE: BuildFormValidator readonly SIGNUP_LIMIT: BuildFormValidator readonly ADMIN_EMAIL: BuildFormValidator readonly TRANSCODING_THREADS: BuildFormValidator @@ -44,6 +45,15 @@ export class CustomConfigValidatorsService { } } + this.CACHE_CAPTIONS_SIZE = { + VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ], + MESSAGES: { + 'required': this.i18n('Captions cache size is required.'), + 'min': this.i18n('Captions cache size must be greater than 1.'), + 'pattern': this.i18n('Captions cache size must be a number.') + } + } + this.SIGNUP_LIMIT = { VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ], MESSAGES: { diff --git a/client/src/app/shared/forms/form-validators/index.ts b/client/src/app/shared/forms/form-validators/index.ts index 487683088..60d735ef7 100644 --- a/client/src/app/shared/forms/form-validators/index.ts +++ b/client/src/app/shared/forms/form-validators/index.ts @@ -8,3 +8,4 @@ export * from './video-abuse-validators.service' export * from './video-channel-validators.service' export * from './video-comment-validators.service' export * from './video-validators.service' +export * from './video-captions-validators.service' diff --git a/client/src/app/shared/forms/form-validators/video-captions-validators.service.ts b/client/src/app/shared/forms/form-validators/video-captions-validators.service.ts new file mode 100644 index 000000000..d1b4667bb --- /dev/null +++ b/client/src/app/shared/forms/form-validators/video-captions-validators.service.ts @@ -0,0 +1,27 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from '@app/shared' + +@Injectable() +export class VideoCaptionsValidatorsService { + readonly VIDEO_CAPTION_LANGUAGE: BuildFormValidator + readonly VIDEO_CAPTION_FILE: BuildFormValidator + + constructor (private i18n: I18n) { + + this.VIDEO_CAPTION_LANGUAGE = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Video caption language is required.') + } + } + + this.VIDEO_CAPTION_FILE = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Video caption file is required.') + } + } + } +} diff --git a/client/src/app/shared/forms/index.ts b/client/src/app/shared/forms/index.ts index 7464bb022..41c321c4c 100644 --- a/client/src/app/shared/forms/index.ts +++ b/client/src/app/shared/forms/index.ts @@ -1,2 +1,3 @@ export * from './form-validators' export * from './form-reactive' +export * from './reactive-file.component' diff --git a/client/src/app/shared/forms/reactive-file.component.html b/client/src/app/shared/forms/reactive-file.component.html new file mode 100644 index 000000000..9fb1c9e3e --- /dev/null +++ b/client/src/app/shared/forms/reactive-file.component.html @@ -0,0 +1,14 @@ +
+
+ {{ inputLabel }} + +
+ +
(extensions: {{ allowedExtensionsMessage }}, max size: {{ maxFileSize | bytes }})
+ +
{{ filename }}
+
diff --git a/client/src/app/shared/forms/reactive-file.component.scss b/client/src/app/shared/forms/reactive-file.component.scss new file mode 100644 index 000000000..d89844264 --- /dev/null +++ b/client/src/app/shared/forms/reactive-file.component.scss @@ -0,0 +1,24 @@ +@import '_variables'; +@import '_mixins'; + +.root { + height: auto; + display: flex; + align-items: center; + + .button-file { + @include peertube-button-file(auto); + + min-width: 190px; + } + + .file-constraints { + margin-left: 5px; + font-size: 13px; + } + + .filename { + font-weight: $font-semibold; + margin-left: 5px; + } +} diff --git a/client/src/app/shared/forms/reactive-file.component.ts b/client/src/app/shared/forms/reactive-file.component.ts new file mode 100644 index 000000000..f5758b643 --- /dev/null +++ b/client/src/app/shared/forms/reactive-file.component.ts @@ -0,0 +1,75 @@ +import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core' +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' +import { NotificationsService } from 'angular2-notifications' +import { I18n } from '@ngx-translate/i18n-polyfill' + +@Component({ + selector: 'my-reactive-file', + styleUrls: [ './reactive-file.component.scss' ], + templateUrl: './reactive-file.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ReactiveFileComponent), + multi: true + } + ] +}) +export class ReactiveFileComponent implements OnInit, ControlValueAccessor { + @Input() inputLabel: string + @Input() inputName: string + @Input() extensions: string[] = [] + @Input() maxFileSize: number + @Input() displayFilename = false + + @Output() fileChanged = new EventEmitter() + + allowedExtensionsMessage = '' + + private file: File + + constructor ( + private notificationsService: NotificationsService, + private i18n: I18n + ) {} + + get filename () { + if (!this.file) return '' + + return this.file.name + } + + ngOnInit () { + this.allowedExtensionsMessage = this.extensions.join(', ') + } + + fileChange (event: any) { + if (event.target.files && event.target.files.length) { + const [ file ] = event.target.files + + if (file.size > this.maxFileSize) { + this.notificationsService.error(this.i18n('Error'), this.i18n('This file is too large.')) + return + } + + this.file = file + + this.propagateChange(this.file) + this.fileChanged.emit(this.file) + } + } + + propagateChange = (_: any) => { /* empty */ } + + writeValue (file: any) { + this.file = file + } + + registerOnChange (fn: (_: any) => void) { + this.propagateChange = fn + } + + registerOnTouched () { + // Unused + } +} -- cgit v1.2.3