From 67ed6552b831df66713bac9e672738796128d33f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 23 Jun 2020 14:10:17 +0200 Subject: Reorganize client shared modules --- .../batch-domains-validators.service.ts | 69 ++++++++++ .../custom-config-validators.service.ts | 98 +++++++++++++ .../form-validators/form-validator.service.ts | 87 ++++++++++++ .../shared/shared-forms/form-validators/host.ts | 8 ++ .../shared/shared-forms/form-validators/index.ts | 17 +++ .../form-validators/instance-validators.service.ts | 62 +++++++++ .../form-validators/login-validators.service.ts | 30 ++++ .../reset-password-validators.service.ts | 20 +++ .../form-validators/user-validators.service.ts | 151 +++++++++++++++++++++ .../video-abuse-validators.service.ts | 30 ++++ .../video-accept-ownership-validators.service.ts | 18 +++ .../video-block-validators.service.ts | 19 +++ .../video-captions-validators.service.ts | 27 ++++ .../video-change-ownership-validators.service.ts | 27 ++++ .../video-channel-validators.service.ts | 64 +++++++++ .../video-comment-validators.service.ts | 20 +++ .../video-playlist-validators.service.ts | 66 +++++++++ .../form-validators/video-validators.service.ts | 102 ++++++++++++++ 18 files changed, 915 insertions(+) create mode 100644 client/src/app/shared/shared-forms/form-validators/batch-domains-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/custom-config-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/form-validator.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/host.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/index.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/instance-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/login-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/reset-password-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/user-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-abuse-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-accept-ownership-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-block-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-captions-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-change-ownership-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-channel-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-comment-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-playlist-validators.service.ts create mode 100644 client/src/app/shared/shared-forms/form-validators/video-validators.service.ts (limited to 'client/src/app/shared/shared-forms/form-validators') diff --git a/client/src/app/shared/shared-forms/form-validators/batch-domains-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/batch-domains-validators.service.ts new file mode 100644 index 000000000..f270b602b --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/batch-domains-validators.service.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@angular/core' +import { ValidatorFn, Validators } from '@angular/forms' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { BuildFormValidator } from './form-validator.service' +import { validateHost } from './host' + +@Injectable() +export class BatchDomainsValidatorsService { + readonly DOMAINS: BuildFormValidator + + constructor (private i18n: I18n) { + this.DOMAINS = { + VALIDATORS: [ Validators.required, this.validDomains, this.isHostsUnique ], + MESSAGES: { + 'required': this.i18n('Domain is required.'), + 'validDomains': this.i18n('Domains entered are invalid.'), + 'uniqueDomains': this.i18n('Domains entered contain duplicates.') + } + } + } + + getNotEmptyHosts (hosts: string) { + return hosts + .split('\n') + .filter((host: string) => host && host.length !== 0) // Eject empty hosts + } + + private validDomains: ValidatorFn = (control) => { + if (!control.value) return null + + const newHostsErrors = [] + const hosts = this.getNotEmptyHosts(control.value) + + for (const host of hosts) { + if (validateHost(host) === false) { + newHostsErrors.push(this.i18n('{{host}} is not valid', { host })) + } + } + + /* Is not valid. */ + if (newHostsErrors.length !== 0) { + return { + 'validDomains': { + reason: 'invalid', + value: newHostsErrors.join('. ') + '.' + } + } + } + + /* Is valid. */ + return null + } + + private isHostsUnique: ValidatorFn = (control) => { + if (!control.value) return null + + const hosts = this.getNotEmptyHosts(control.value) + + if (hosts.every((host: string) => hosts.indexOf(host) === hosts.lastIndexOf(host))) { + return null + } else { + return { + 'uniqueDomains': { + reason: 'invalid' + } + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/custom-config-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/custom-config-validators.service.ts new file mode 100644 index 000000000..c77aba6a1 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/custom-config-validators.service.ts @@ -0,0 +1,98 @@ +import { Validators } from '@angular/forms' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { BuildFormValidator } from './form-validator.service' +import { Injectable } from '@angular/core' + +@Injectable() +export class CustomConfigValidatorsService { + readonly INSTANCE_NAME: BuildFormValidator + 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 + readonly INDEX_URL: BuildFormValidator + readonly SEARCH_INDEX_URL: BuildFormValidator + + constructor (private i18n: I18n) { + this.INSTANCE_NAME = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Instance name is required.') + } + } + + this.INSTANCE_SHORT_DESCRIPTION = { + VALIDATORS: [ Validators.max(250) ], + MESSAGES: { + 'max': this.i18n('Short description should not be longer than 250 characters.') + } + } + + this.SERVICES_TWITTER_USERNAME = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Twitter username is required.') + } + } + + this.CACHE_PREVIEWS_SIZE = { + VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ], + MESSAGES: { + 'required': this.i18n('Previews cache size is required.'), + 'min': this.i18n('Previews cache size must be greater than 1.'), + 'pattern': this.i18n('Previews cache size must be a number.') + } + } + + 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: { + 'required': this.i18n('Signup limit is required.'), + 'min': this.i18n('Signup limit must be greater than 1.'), + 'pattern': this.i18n('Signup limit must be a number.') + } + } + + this.ADMIN_EMAIL = { + VALIDATORS: [ Validators.required, Validators.email ], + MESSAGES: { + 'required': this.i18n('Admin email is required.'), + 'email': this.i18n('Admin email must be valid.') + } + } + + this.TRANSCODING_THREADS = { + VALIDATORS: [ Validators.required, Validators.min(0) ], + MESSAGES: { + 'required': this.i18n('Transcoding threads is required.'), + 'min': this.i18n('Transcoding threads must be greater or equal to 0.') + } + } + + this.INDEX_URL = { + VALIDATORS: [ Validators.pattern(/^https:\/\//) ], + MESSAGES: { + 'pattern': this.i18n('Index URL should be a URL') + } + } + + this.SEARCH_INDEX_URL = { + VALIDATORS: [ Validators.pattern(/^https?:\/\//) ], + MESSAGES: { + 'pattern': this.i18n('Search index URL should be a URL') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/form-validator.service.ts b/client/src/app/shared/shared-forms/form-validators/form-validator.service.ts new file mode 100644 index 000000000..dec7d8d9a --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/form-validator.service.ts @@ -0,0 +1,87 @@ +import { FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms' +import { Injectable } from '@angular/core' +import { FormReactiveErrors, FormReactiveValidationMessages } from '../form-reactive' + +export type BuildFormValidator = { + VALIDATORS: ValidatorFn[], + MESSAGES: { [ name: string ]: string } +} +export type BuildFormArgument = { + [ id: string ]: BuildFormValidator | BuildFormArgument +} +export type BuildFormDefaultValues = { + [ name: string ]: string | string[] | BuildFormDefaultValues +} + +@Injectable() +export class FormValidatorService { + + constructor ( + private formBuilder: FormBuilder + ) {} + + buildForm (obj: BuildFormArgument, defaultValues: BuildFormDefaultValues = {}) { + const formErrors: FormReactiveErrors = {} + const validationMessages: FormReactiveValidationMessages = {} + const group: { [key: string]: any } = {} + + for (const name of Object.keys(obj)) { + formErrors[name] = '' + + const field = obj[name] + if (this.isRecursiveField(field)) { + const result = this.buildForm(field as BuildFormArgument, defaultValues[name] as BuildFormDefaultValues) + group[name] = result.form + formErrors[name] = result.formErrors + validationMessages[name] = result.validationMessages + + continue + } + + if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string } + + const defaultValue = defaultValues[name] || '' + + if (field && field.VALIDATORS) group[name] = [ defaultValue, field.VALIDATORS ] + else group[name] = [ defaultValue ] + } + + const form = this.formBuilder.group(group) + return { form, formErrors, validationMessages } + } + + updateForm ( + form: FormGroup, + formErrors: FormReactiveErrors, + validationMessages: FormReactiveValidationMessages, + obj: BuildFormArgument, + defaultValues: BuildFormDefaultValues = {} + ) { + for (const name of Object.keys(obj)) { + formErrors[name] = '' + + const field = obj[name] + if (this.isRecursiveField(field)) { + this.updateForm( + form[name], + formErrors[name] as FormReactiveErrors, + validationMessages[name] as FormReactiveValidationMessages, + obj[name] as BuildFormArgument, + defaultValues[name] as BuildFormDefaultValues + ) + continue + } + + if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string } + + const defaultValue = defaultValues[name] || '' + + if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[])) + else form.addControl(name, new FormControl(defaultValue)) + } + } + + private isRecursiveField (field: any) { + return field && typeof field === 'object' && !field.MESSAGES && !field.VALIDATORS + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/host.ts b/client/src/app/shared/shared-forms/form-validators/host.ts new file mode 100644 index 000000000..c18a35f9b --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/host.ts @@ -0,0 +1,8 @@ +export function validateHost (value: string) { + // Thanks to http://stackoverflow.com/a/106223 + const HOST_REGEXP = new RegExp( + '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' + ) + + return HOST_REGEXP.test(value) +} diff --git a/client/src/app/shared/shared-forms/form-validators/index.ts b/client/src/app/shared/shared-forms/form-validators/index.ts new file mode 100644 index 000000000..8b71841a9 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/index.ts @@ -0,0 +1,17 @@ +export * from './batch-domains-validators.service' +export * from './custom-config-validators.service' +export * from './form-validator.service' +export * from './host' +export * from './instance-validators.service' +export * from './login-validators.service' +export * from './reset-password-validators.service' +export * from './user-validators.service' +export * from './video-abuse-validators.service' +export * from './video-accept-ownership-validators.service' +export * from './video-block-validators.service' +export * from './video-captions-validators.service' +export * from './video-change-ownership-validators.service' +export * from './video-channel-validators.service' +export * from './video-comment-validators.service' +export * from './video-playlist-validators.service' +export * from './video-validators.service' diff --git a/client/src/app/shared/shared-forms/form-validators/instance-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/instance-validators.service.ts new file mode 100644 index 000000000..96a35a48f --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/instance-validators.service.ts @@ -0,0 +1,62 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { BuildFormValidator } from './form-validator.service' +import { Injectable } from '@angular/core' + +@Injectable() +export class InstanceValidatorsService { + readonly FROM_EMAIL: BuildFormValidator + readonly FROM_NAME: BuildFormValidator + readonly SUBJECT: BuildFormValidator + readonly BODY: BuildFormValidator + + constructor (private i18n: I18n) { + + this.FROM_EMAIL = { + VALIDATORS: [ Validators.required, Validators.email ], + MESSAGES: { + 'required': this.i18n('Email is required.'), + 'email': this.i18n('Email must be valid.') + } + } + + this.FROM_NAME = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(120) + ], + MESSAGES: { + 'required': this.i18n('Your name is required.'), + 'minlength': this.i18n('Your name must be at least 1 character long.'), + 'maxlength': this.i18n('Your name cannot be more than 120 characters long.') + } + } + + this.SUBJECT = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(120) + ], + MESSAGES: { + 'required': this.i18n('A subject is required.'), + 'minlength': this.i18n('The subject must be at least 1 character long.'), + 'maxlength': this.i18n('The subject cannot be more than 120 characters long.') + } + } + + this.BODY = { + VALIDATORS: [ + Validators.required, + Validators.minLength(3), + Validators.maxLength(5000) + ], + MESSAGES: { + 'required': this.i18n('A message is required.'), + 'minlength': this.i18n('The message must be at least 3 characters long.'), + 'maxlength': this.i18n('The message cannot be more than 5000 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/login-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/login-validators.service.ts new file mode 100644 index 000000000..a5837357e --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/login-validators.service.ts @@ -0,0 +1,30 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class LoginValidatorsService { + readonly LOGIN_USERNAME: BuildFormValidator + readonly LOGIN_PASSWORD: BuildFormValidator + + constructor (private i18n: I18n) { + this.LOGIN_USERNAME = { + VALIDATORS: [ + Validators.required + ], + MESSAGES: { + 'required': this.i18n('Username is required.') + } + } + + this.LOGIN_PASSWORD = { + VALIDATORS: [ + Validators.required + ], + MESSAGES: { + 'required': this.i18n('Password is required.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/reset-password-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/reset-password-validators.service.ts new file mode 100644 index 000000000..d2085a309 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/reset-password-validators.service.ts @@ -0,0 +1,20 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class ResetPasswordValidatorsService { + readonly RESET_PASSWORD_CONFIRM: BuildFormValidator + + constructor (private i18n: I18n) { + this.RESET_PASSWORD_CONFIRM = { + VALIDATORS: [ + Validators.required + ], + MESSAGES: { + 'required': this.i18n('Confirmation of the password is required.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/user-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/user-validators.service.ts new file mode 100644 index 000000000..bd3030a54 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/user-validators.service.ts @@ -0,0 +1,151 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { BuildFormValidator } from './form-validator.service' +import { Injectable } from '@angular/core' + +@Injectable() +export class UserValidatorsService { + readonly USER_USERNAME: BuildFormValidator + readonly USER_EMAIL: BuildFormValidator + readonly USER_PASSWORD: BuildFormValidator + readonly USER_PASSWORD_OPTIONAL: BuildFormValidator + readonly USER_CONFIRM_PASSWORD: BuildFormValidator + readonly USER_VIDEO_QUOTA: BuildFormValidator + readonly USER_VIDEO_QUOTA_DAILY: BuildFormValidator + readonly USER_ROLE: BuildFormValidator + readonly USER_DISPLAY_NAME_REQUIRED: BuildFormValidator + readonly USER_DESCRIPTION: BuildFormValidator + readonly USER_TERMS: BuildFormValidator + + readonly USER_BAN_REASON: BuildFormValidator + + constructor (private i18n: I18n) { + + this.USER_USERNAME = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(50), + Validators.pattern(/^[a-z0-9][a-z0-9._]*$/) + ], + MESSAGES: { + 'required': this.i18n('Username is required.'), + 'minlength': this.i18n('Username must be at least 1 character long.'), + 'maxlength': this.i18n('Username cannot be more than 50 characters long.'), + 'pattern': this.i18n('Username should be lowercase alphanumeric; dots and underscores are allowed.') + } + } + + this.USER_EMAIL = { + VALIDATORS: [ Validators.required, Validators.email ], + MESSAGES: { + 'required': this.i18n('Email is required.'), + 'email': this.i18n('Email must be valid.') + } + } + + this.USER_PASSWORD = { + VALIDATORS: [ + Validators.required, + Validators.minLength(6), + Validators.maxLength(255) + ], + MESSAGES: { + 'required': this.i18n('Password is required.'), + 'minlength': this.i18n('Password must be at least 6 characters long.'), + 'maxlength': this.i18n('Password cannot be more than 255 characters long.') + } + } + + this.USER_PASSWORD_OPTIONAL = { + VALIDATORS: [ + Validators.minLength(6), + Validators.maxLength(255) + ], + MESSAGES: { + 'minlength': this.i18n('Password must be at least 6 characters long.'), + 'maxlength': this.i18n('Password cannot be more than 255 characters long.') + } + } + + this.USER_CONFIRM_PASSWORD = { + VALIDATORS: [], + MESSAGES: { + 'matchPassword': this.i18n('The new password and the confirmed password do not correspond.') + } + } + + this.USER_VIDEO_QUOTA = { + VALIDATORS: [ Validators.required, Validators.min(-1) ], + MESSAGES: { + 'required': this.i18n('Video quota is required.'), + 'min': this.i18n('Quota must be greater than -1.') + } + } + this.USER_VIDEO_QUOTA_DAILY = { + VALIDATORS: [ Validators.required, Validators.min(-1) ], + MESSAGES: { + 'required': this.i18n('Daily upload limit is required.'), + 'min': this.i18n('Daily upload limit must be greater than -1.') + } + } + + this.USER_ROLE = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('User role is required.') + } + } + + this.USER_DISPLAY_NAME_REQUIRED = this.getDisplayName(true) + + this.USER_DESCRIPTION = { + VALIDATORS: [ + Validators.minLength(3), + Validators.maxLength(1000) + ], + MESSAGES: { + 'minlength': this.i18n('Description must be at least 3 characters long.'), + 'maxlength': this.i18n('Description cannot be more than 1000 characters long.') + } + } + + this.USER_TERMS = { + VALIDATORS: [ + Validators.requiredTrue + ], + MESSAGES: { + 'required': this.i18n('You must agree with the instance terms in order to register on it.') + } + } + + this.USER_BAN_REASON = { + VALIDATORS: [ + Validators.minLength(3), + Validators.maxLength(250) + ], + MESSAGES: { + 'minlength': this.i18n('Ban reason must be at least 3 characters long.'), + 'maxlength': this.i18n('Ban reason cannot be more than 250 characters long.') + } + } + } + + private getDisplayName (required: boolean) { + const control = { + VALIDATORS: [ + Validators.minLength(1), + Validators.maxLength(120) + ], + MESSAGES: { + 'required': this.i18n('Display name is required.'), + 'minlength': this.i18n('Display name must be at least 1 character long.'), + 'maxlength': this.i18n('Display name cannot be more than 50 characters long.') + } + } + + if (required) control.VALIDATORS.push(Validators.required) + + return control + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-abuse-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-abuse-validators.service.ts new file mode 100644 index 000000000..aae56d607 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-abuse-validators.service.ts @@ -0,0 +1,30 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoAbuseValidatorsService { + readonly VIDEO_ABUSE_REASON: BuildFormValidator + readonly VIDEO_ABUSE_MODERATION_COMMENT: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_ABUSE_REASON = { + VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ], + MESSAGES: { + 'required': this.i18n('Report reason is required.'), + 'minlength': this.i18n('Report reason must be at least 2 characters long.'), + 'maxlength': this.i18n('Report reason cannot be more than 3000 characters long.') + } + } + + this.VIDEO_ABUSE_MODERATION_COMMENT = { + VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ], + MESSAGES: { + 'required': this.i18n('Moderation comment is required.'), + 'minlength': this.i18n('Moderation comment must be at least 2 characters long.'), + 'maxlength': this.i18n('Moderation comment cannot be more than 3000 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-accept-ownership-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-accept-ownership-validators.service.ts new file mode 100644 index 000000000..998d616ec --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-accept-ownership-validators.service.ts @@ -0,0 +1,18 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoAcceptOwnershipValidatorsService { + readonly CHANNEL: BuildFormValidator + + constructor (private i18n: I18n) { + this.CHANNEL = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('The channel is required.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-block-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-block-validators.service.ts new file mode 100644 index 000000000..ddf0ab5eb --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-block-validators.service.ts @@ -0,0 +1,19 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoBlockValidatorsService { + readonly VIDEO_BLOCK_REASON: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_BLOCK_REASON = { + VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ], + MESSAGES: { + 'minlength': this.i18n('Block reason must be at least 2 characters long.'), + 'maxlength': this.i18n('Block reason cannot be more than 300 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-captions-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-captions-validators.service.ts new file mode 100644 index 000000000..280d28414 --- /dev/null +++ b/client/src/app/shared/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 './form-validator.service' + +@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/shared-forms/form-validators/video-change-ownership-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-change-ownership-validators.service.ts new file mode 100644 index 000000000..59659defd --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-change-ownership-validators.service.ts @@ -0,0 +1,27 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { AbstractControl, ValidationErrors, Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoChangeOwnershipValidatorsService { + readonly USERNAME: BuildFormValidator + + constructor (private i18n: I18n) { + this.USERNAME = { + VALIDATORS: [ Validators.required, this.localAccountValidator ], + MESSAGES: { + 'required': this.i18n('The username is required.'), + 'localAccountOnly': this.i18n('You can only transfer ownership to a local account') + } + } + } + + localAccountValidator (control: AbstractControl): ValidationErrors { + if (control.value.includes('@')) { + return { 'localAccountOnly': true } + } + + return null + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-channel-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-channel-validators.service.ts new file mode 100644 index 000000000..bb650b149 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-channel-validators.service.ts @@ -0,0 +1,64 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoChannelValidatorsService { + readonly VIDEO_CHANNEL_NAME: BuildFormValidator + readonly VIDEO_CHANNEL_DISPLAY_NAME: BuildFormValidator + readonly VIDEO_CHANNEL_DESCRIPTION: BuildFormValidator + readonly VIDEO_CHANNEL_SUPPORT: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_CHANNEL_NAME = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(50), + Validators.pattern(/^[a-z0-9][a-z0-9._]*$/) + ], + MESSAGES: { + 'required': this.i18n('Name is required.'), + 'minlength': this.i18n('Name must be at least 1 character long.'), + 'maxlength': this.i18n('Name cannot be more than 50 characters long.'), + 'pattern': this.i18n('Name should be lowercase alphanumeric; dots and underscores are allowed.') + } + } + + this.VIDEO_CHANNEL_DISPLAY_NAME = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(50) + ], + MESSAGES: { + 'required': i18n('Display name is required.'), + 'minlength': i18n('Display name must be at least 1 character long.'), + 'maxlength': i18n('Display name cannot be more than 50 characters long.') + } + } + + this.VIDEO_CHANNEL_DESCRIPTION = { + VALIDATORS: [ + Validators.minLength(3), + Validators.maxLength(1000) + ], + MESSAGES: { + 'minlength': i18n('Description must be at least 3 characters long.'), + 'maxlength': i18n('Description cannot be more than 1000 characters long.') + } + } + + this.VIDEO_CHANNEL_SUPPORT = { + VALIDATORS: [ + Validators.minLength(3), + Validators.maxLength(1000) + ], + MESSAGES: { + 'minlength': i18n('Support text must be at least 3 characters long.'), + 'maxlength': i18n('Support text cannot be more than 1000 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-comment-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-comment-validators.service.ts new file mode 100644 index 000000000..97c8e967e --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-comment-validators.service.ts @@ -0,0 +1,20 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoCommentValidatorsService { + readonly VIDEO_COMMENT_TEXT: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_COMMENT_TEXT = { + VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ], + MESSAGES: { + 'required': this.i18n('Comment is required.'), + 'minlength': this.i18n('Comment must be at least 2 characters long.'), + 'maxlength': this.i18n('Comment cannot be more than 3000 characters long.') + } + } + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-playlist-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-playlist-validators.service.ts new file mode 100644 index 000000000..ab9c43625 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-playlist-validators.service.ts @@ -0,0 +1,66 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { AbstractControl, FormControl, Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' +import { VideoPlaylistPrivacy } from '@shared/models' + +@Injectable() +export class VideoPlaylistValidatorsService { + readonly VIDEO_PLAYLIST_DISPLAY_NAME: BuildFormValidator + readonly VIDEO_PLAYLIST_PRIVACY: BuildFormValidator + readonly VIDEO_PLAYLIST_DESCRIPTION: BuildFormValidator + readonly VIDEO_PLAYLIST_CHANNEL_ID: BuildFormValidator + + constructor (private i18n: I18n) { + this.VIDEO_PLAYLIST_DISPLAY_NAME = { + VALIDATORS: [ + Validators.required, + Validators.minLength(1), + Validators.maxLength(120) + ], + MESSAGES: { + 'required': this.i18n('Display name is required.'), + 'minlength': this.i18n('Display name must be at least 1 character long.'), + 'maxlength': this.i18n('Display name cannot be more than 120 characters long.') + } + } + + this.VIDEO_PLAYLIST_PRIVACY = { + VALIDATORS: [ + Validators.required + ], + MESSAGES: { + 'required': this.i18n('Privacy is required.') + } + } + + this.VIDEO_PLAYLIST_DESCRIPTION = { + VALIDATORS: [ + Validators.minLength(3), + Validators.maxLength(1000) + ], + MESSAGES: { + 'minlength': i18n('Description must be at least 3 characters long.'), + 'maxlength': i18n('Description cannot be more than 1000 characters long.') + } + } + + this.VIDEO_PLAYLIST_CHANNEL_ID = { + VALIDATORS: [ ], + MESSAGES: { + 'required': this.i18n('The channel is required when the playlist is public.') + } + } + } + + setChannelValidator (channelControl: AbstractControl, privacy: VideoPlaylistPrivacy) { + if (privacy.toString() === VideoPlaylistPrivacy.PUBLIC.toString()) { + channelControl.setValidators([ Validators.required ]) + } else { + channelControl.setValidators(null) + } + + channelControl.markAsDirty() + channelControl.updateValueAndValidity() + } +} diff --git a/client/src/app/shared/shared-forms/form-validators/video-validators.service.ts b/client/src/app/shared/shared-forms/form-validators/video-validators.service.ts new file mode 100644 index 000000000..9b24e4f62 --- /dev/null +++ b/client/src/app/shared/shared-forms/form-validators/video-validators.service.ts @@ -0,0 +1,102 @@ +import { I18n } from '@ngx-translate/i18n-polyfill' +import { Validators } from '@angular/forms' +import { Injectable } from '@angular/core' +import { BuildFormValidator } from './form-validator.service' + +@Injectable() +export class VideoValidatorsService { + readonly VIDEO_NAME: BuildFormValidator + readonly VIDEO_PRIVACY: BuildFormValidator + readonly VIDEO_CATEGORY: BuildFormValidator + readonly VIDEO_LICENCE: BuildFormValidator + readonly VIDEO_LANGUAGE: BuildFormValidator + readonly VIDEO_IMAGE: BuildFormValidator + readonly VIDEO_CHANNEL: BuildFormValidator + readonly VIDEO_DESCRIPTION: BuildFormValidator + readonly VIDEO_TAGS: BuildFormValidator + readonly VIDEO_SUPPORT: BuildFormValidator + readonly VIDEO_SCHEDULE_PUBLICATION_AT: BuildFormValidator + readonly VIDEO_ORIGINALLY_PUBLISHED_AT: BuildFormValidator + + constructor (private i18n: I18n) { + + this.VIDEO_NAME = { + VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(120) ], + MESSAGES: { + 'required': this.i18n('Video name is required.'), + 'minlength': this.i18n('Video name must be at least 3 characters long.'), + 'maxlength': this.i18n('Video name cannot be more than 120 characters long.') + } + } + + this.VIDEO_PRIVACY = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Video privacy is required.') + } + } + + this.VIDEO_CATEGORY = { + VALIDATORS: [ ], + MESSAGES: {} + } + + this.VIDEO_LICENCE = { + VALIDATORS: [ ], + MESSAGES: {} + } + + this.VIDEO_LANGUAGE = { + VALIDATORS: [ ], + MESSAGES: {} + } + + this.VIDEO_IMAGE = { + VALIDATORS: [ ], + MESSAGES: {} + } + + this.VIDEO_CHANNEL = { + VALIDATORS: [ Validators.required ], + MESSAGES: { + 'required': this.i18n('Video channel is required.') + } + } + + this.VIDEO_DESCRIPTION = { + VALIDATORS: [ Validators.minLength(3), Validators.maxLength(10000) ], + MESSAGES: { + 'minlength': this.i18n('Video description must be at least 3 characters long.'), + 'maxlength': this.i18n('Video description cannot be more than 10000 characters long.') + } + } + + this.VIDEO_TAGS = { + VALIDATORS: [ Validators.minLength(2), Validators.maxLength(30) ], + MESSAGES: { + 'minlength': this.i18n('A tag should be more than 2 characters long.'), + 'maxlength': this.i18n('A tag should be less than 30 characters long.') + } + } + + this.VIDEO_SUPPORT = { + VALIDATORS: [ Validators.minLength(3), Validators.maxLength(1000) ], + MESSAGES: { + 'minlength': this.i18n('Video support must be at least 3 characters long.'), + 'maxlength': this.i18n('Video support cannot be more than 1000 characters long.') + } + } + + this.VIDEO_SCHEDULE_PUBLICATION_AT = { + VALIDATORS: [ ], + MESSAGES: { + 'required': this.i18n('A date is required to schedule video update.') + } + } + + this.VIDEO_ORIGINALLY_PUBLISHED_AT = { + VALIDATORS: [ ], + MESSAGES: {} + } + } +} -- cgit v1.2.3