Migrate client to eslint
This commit is contained in:
parent
adb8809d43
commit
9df52d660f
169
client/.eslintrc.json
Normal file
169
client/.eslintrc.json
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
"ignorePatterns": [
|
||||||
|
"projects/**/*",
|
||||||
|
"node_modules/"
|
||||||
|
],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"*.ts"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"project": [
|
||||||
|
"tsconfig.json",
|
||||||
|
"e2e/tsconfig.json"
|
||||||
|
],
|
||||||
|
"createDefaultProgram": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"../.eslintrc.json",
|
||||||
|
"plugin:@angular-eslint/ng-cli-compat",
|
||||||
|
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
|
||||||
|
"plugin:@angular-eslint/template/process-inline-templates"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"lines-between-class-members": "off",
|
||||||
|
"@typescript-eslint/lines-between-class-members": [ "off" ],
|
||||||
|
"arrow-body-style": "off",
|
||||||
|
"import/no-webpack-loader-syntax": "off",
|
||||||
|
"no-underscore-dangle": "off",
|
||||||
|
"node/no-callback-literal": "off",
|
||||||
|
"@angular-eslint/component-selector": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"type": [ "element", "attribute" ],
|
||||||
|
"prefix": "my",
|
||||||
|
"style": "kebab-case"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@angular-eslint/directive-selector": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"type": [ "element", "attribute" ],
|
||||||
|
"prefix": "my",
|
||||||
|
"style": "camelCase"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-this-alias": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowDestructuring": true,
|
||||||
|
"allowedNames": ["self", "player"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/prefer-readonly": "off",
|
||||||
|
"@angular-eslint/use-component-view-encapsulation": "error",
|
||||||
|
"prefer-arrow/prefer-arrow-functions": "off",
|
||||||
|
"@typescript-eslint/await-thenable": "error",
|
||||||
|
"@typescript-eslint/consistent-type-definitions": "off",
|
||||||
|
"@typescript-eslint/dot-notation": "off",
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": [
|
||||||
|
"off",
|
||||||
|
{
|
||||||
|
"accessibility": "explicit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/member-ordering": [
|
||||||
|
"off"
|
||||||
|
],
|
||||||
|
"@typescript-eslint/member-delimiter-style": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"multiline": {
|
||||||
|
"delimiter": "none",
|
||||||
|
"requireLast": true
|
||||||
|
},
|
||||||
|
"singleline": {
|
||||||
|
"delimiter": "comma",
|
||||||
|
"requireLast": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/prefer-for-of": "off",
|
||||||
|
"@typescript-eslint/no-empty-function": "error",
|
||||||
|
"@typescript-eslint/no-floating-promises": "off",
|
||||||
|
"@typescript-eslint/no-inferrable-types": "error",
|
||||||
|
"@typescript-eslint/no-shadow": [
|
||||||
|
"off",
|
||||||
|
{
|
||||||
|
"hoist": "all"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
|
"@typescript-eslint/no-unused-expressions": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowTaggedTemplates": true,
|
||||||
|
"allowShortCircuit": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/quotes": [
|
||||||
|
"error",
|
||||||
|
"single",
|
||||||
|
{
|
||||||
|
"avoidEscape": true,
|
||||||
|
"allowTemplateLiterals": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/semi": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"brace-style": [
|
||||||
|
"error",
|
||||||
|
"1tbs"
|
||||||
|
],
|
||||||
|
"comma-dangle": "error",
|
||||||
|
"curly": [
|
||||||
|
"error",
|
||||||
|
"multi-line"
|
||||||
|
],
|
||||||
|
"dot-notation": "off",
|
||||||
|
"no-useless-return": "off",
|
||||||
|
"indent": "off",
|
||||||
|
"no-bitwise": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-return-assign": "off",
|
||||||
|
"no-constant-condition": "error",
|
||||||
|
"no-control-regex": "error",
|
||||||
|
"no-duplicate-imports": "error",
|
||||||
|
"no-empty": "error",
|
||||||
|
"no-empty-function": [
|
||||||
|
"error",
|
||||||
|
{ "allow": [ "constructors" ] }
|
||||||
|
],
|
||||||
|
"no-invalid-regexp": "error",
|
||||||
|
"no-multiple-empty-lines": "error",
|
||||||
|
"no-redeclare": "error",
|
||||||
|
"no-regex-spaces": "error",
|
||||||
|
"no-return-await": "error",
|
||||||
|
"no-shadow": "off",
|
||||||
|
"no-unused-expressions": "error",
|
||||||
|
"semi": "error",
|
||||||
|
"space-before-function-paren": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"space-in-parens": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"object-shorthand": [
|
||||||
|
"error",
|
||||||
|
"properties"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"*.html"
|
||||||
|
],
|
||||||
|
"extends": [
|
||||||
|
"plugin:@angular-eslint/template/recommended"
|
||||||
|
],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -203,7 +203,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ar-locale": {
|
"ar-locale": {
|
||||||
"localize": ["ar"],
|
"localize": [
|
||||||
|
"ar"
|
||||||
|
],
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"type": "anyComponentStyle",
|
"type": "anyComponentStyle",
|
||||||
|
@ -295,13 +297,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"builder": "@angular-eslint/builder:lint",
|
||||||
"options": {
|
"options": {
|
||||||
"tsConfig": [
|
"lintFilePatterns": [
|
||||||
"tsconfig.json"
|
"src/**/*.ts",
|
||||||
],
|
"src/**/*.html"
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -378,17 +378,6 @@
|
||||||
"protractorConfig": "e2e/local-protractor.conf.js"
|
"protractorConfig": "e2e/local-protractor.conf.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"lint": {
|
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
|
||||||
"options": {
|
|
||||||
"tsConfig": [
|
|
||||||
"e2e/tsconfig.e2e.json"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ exports.config = {
|
||||||
|
|
||||||
onPrepare() {
|
onPrepare() {
|
||||||
require('ts-node').register({
|
require('ts-node').register({
|
||||||
project: require('path').join(__dirname, './tsconfig.e2e.json')
|
project: require('path').join(__dirname, './tsconfig.json')
|
||||||
})
|
})
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }))
|
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ exports.config = {
|
||||||
|
|
||||||
onPrepare() {
|
onPrepare() {
|
||||||
require('ts-node').register({
|
require('ts-node').register({
|
||||||
project: require('path').join(__dirname, './tsconfig.e2e.json')
|
project: require('path').join(__dirname, './tsconfig.json')
|
||||||
})
|
})
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({
|
jasmine.getEnv().addReporter(new SpecReporter({
|
||||||
spec: { displayStacktrace: 'raw' }
|
spec: { displayStacktrace: 'raw' }
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "npm run lint-ts && npm run lint-scss",
|
"lint": "npm run lint-ts && npm run lint-scss",
|
||||||
"lint-ts": "tslint --project ./tsconfig.json -c ./tslint.json 'src/app/**/*.ts' 'src/standalone/**/*.ts'",
|
"lint-ts": "eslint --ext .ts src/standalone/**/*.ts && npm run ng lint",
|
||||||
"lint-scss": "stylelint 'src/**/*.scss'",
|
"lint-scss": "stylelint 'src/**/*.scss'",
|
||||||
"webpack": "webpack",
|
"webpack": "webpack",
|
||||||
"tslint": "tslint",
|
"eslint": "eslint",
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"webpack-bundle-analyzer": "webpack-bundle-analyzer",
|
"webpack-bundle-analyzer": "webpack-bundle-analyzer",
|
||||||
"webdriver-manager": "webdriver-manager",
|
"webdriver-manager": "webdriver-manager",
|
||||||
|
@ -27,6 +27,11 @@
|
||||||
"typings": "*.d.ts",
|
"typings": "*.d.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^12.0.0",
|
"@angular-devkit/build-angular": "^12.0.0",
|
||||||
|
"@angular-eslint/builder": "12.3.1",
|
||||||
|
"@angular-eslint/eslint-plugin": "12.3.1",
|
||||||
|
"@angular-eslint/eslint-plugin-template": "12.3.1",
|
||||||
|
"@angular-eslint/schematics": "12.3.1",
|
||||||
|
"@angular-eslint/template-parser": "12.3.1",
|
||||||
"@angular/animations": "^12.0.0",
|
"@angular/animations": "^12.0.0",
|
||||||
"@angular/cdk": "^12.0.0",
|
"@angular/cdk": "^12.0.0",
|
||||||
"@angular/cli": "^12.0.0",
|
"@angular/cli": "^12.0.0",
|
||||||
|
@ -64,17 +69,22 @@
|
||||||
"@types/sha.js": "^2.4.0",
|
"@types/sha.js": "^2.4.0",
|
||||||
"@types/video.js": "^7.3.8",
|
"@types/video.js": "^7.3.8",
|
||||||
"@types/webtorrent": "^0.109.0",
|
"@types/webtorrent": "^0.109.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "4.28.2",
|
||||||
|
"@typescript-eslint/parser": "4.28.2",
|
||||||
"angular2-hotkeys": "^2.1.2",
|
"angular2-hotkeys": "^2.1.2",
|
||||||
"angularx-qrcode": "11.0.0",
|
"angularx-qrcode": "11.0.0",
|
||||||
"bootstrap": "^4.1.3",
|
"bootstrap": "^4.1.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cache-chunk-store": "^3.0.0",
|
"cache-chunk-store": "^3.0.0",
|
||||||
"chart.js": "^2.9.3",
|
"chart.js": "^2.9.3",
|
||||||
"codelyzer": "^6.0.0",
|
|
||||||
"core-js": "^3.1.4",
|
"core-js": "^3.1.4",
|
||||||
"css-loader": "^6.2.0",
|
"css-loader": "^6.2.0",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"dexie": "^3.0.0",
|
"dexie": "^3.0.0",
|
||||||
|
"eslint": "^7.26.0",
|
||||||
|
"eslint-plugin-import": "latest",
|
||||||
|
"eslint-plugin-jsdoc": "latest",
|
||||||
|
"eslint-plugin-prefer-arrow": "latest",
|
||||||
"focus-visible": "^5.0.2",
|
"focus-visible": "^5.0.2",
|
||||||
"hls.js": "^1.0.7",
|
"hls.js": "^1.0.7",
|
||||||
"html-loader": "^2.1.2",
|
"html-loader": "^2.1.2",
|
||||||
|
@ -112,9 +122,6 @@
|
||||||
"terser-webpack-plugin": "^5.1.2",
|
"terser-webpack-plugin": "^5.1.2",
|
||||||
"ts-loader": "^9.2.2",
|
"ts-loader": "^9.2.2",
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.0",
|
||||||
"tslint": "~6.1.0",
|
|
||||||
"tslint-angular": "^3.0.2",
|
|
||||||
"tslint-config-standard": "^9.0.0",
|
|
||||||
"typescript": "~4.3.4",
|
"typescript": "~4.3.4",
|
||||||
"video.js": "^7",
|
"video.js": "^7",
|
||||||
"videojs-contextmenu-pt": "^5.4.1",
|
"videojs-contextmenu-pt": "^5.4.1",
|
||||||
|
|
|
@ -90,7 +90,7 @@ export class AboutFollowsComponent implements OnInit {
|
||||||
private loadMoreFollowers (reset = false) {
|
private loadMoreFollowers (reset = false) {
|
||||||
const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination)
|
const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination)
|
||||||
|
|
||||||
this.followService.getFollowers({ pagination: pagination, sort: this.sort, state: 'accepted' })
|
this.followService.getFollowers({ pagination, sort: this.sort, state: 'accepted' })
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: resultList => {
|
next: resultList => {
|
||||||
if (reset) this.followers = []
|
if (reset) this.followers = []
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { RouterModule, Routes } from '@angular/router'
|
||||||
import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
|
import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
|
||||||
import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
|
import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
|
||||||
import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
|
import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
|
||||||
import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
|
|
||||||
import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
|
import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
|
||||||
import { AboutComponent } from './about.component'
|
import { AboutComponent } from './about.component'
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { from, Subject, Subscription } from 'rxjs'
|
import { from, Subject, Subscription } from 'rxjs'
|
||||||
import { concatMap, map, switchMap, tap } from 'rxjs/operators'
|
import { concatMap, map, switchMap, tap } from 'rxjs/operators'
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { ComponentPagination, hasMoreItems, MarkdownService, ScreenService, User, UserService } from '@app/core'
|
import { ComponentPagination, hasMoreItems, MarkdownService, User, UserService } from '@app/core'
|
||||||
import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
|
import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
|
||||||
import { NSFWPolicyType, VideoSortField } from '@shared/models'
|
|
||||||
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
|
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
|
||||||
|
import { NSFWPolicyType, VideoSortField } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-account-video-channels',
|
selector: 'my-account-video-channels',
|
||||||
|
@ -87,7 +87,9 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.videoChannelService.listAccountVideoChannels(options)
|
this.videoChannelService.listAccountVideoChannels(options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(res => this.channelPagination.totalItems = res.total),
|
tap(res => {
|
||||||
|
this.channelPagination.totalItems = res.total
|
||||||
|
}),
|
||||||
switchMap(res => from(res.data)),
|
switchMap(res => from(res.data)),
|
||||||
concatMap(videoChannel => {
|
concatMap(videoChannel => {
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { forkJoin, Subscription } from 'rxjs'
|
import { forkJoin, Subscription } from 'rxjs'
|
||||||
import { first, tap } from 'rxjs/operators'
|
import { first } from 'rxjs/operators'
|
||||||
import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
|
import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
|
import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
|
||||||
|
|
|
@ -71,14 +71,14 @@
|
||||||
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
|
<my-list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
|
||||||
|
|
||||||
<simple-search-input
|
<my-simple-search-input
|
||||||
[alwaysShow]="!isInSmallView()" (searchChanged)="searchChanged($event)"
|
[alwaysShow]="!isInSmallView()" (searchChanged)="searchChanged($event)"
|
||||||
(inputDisplayChanged)="onSearchInputDisplayChanged($event)" name="search-videos"
|
(inputDisplayChanged)="onSearchInputDisplayChanged($event)" name="search-videos"
|
||||||
i18n-iconTitle icon-title="Search account videos"
|
i18n-iconTitle icon-title="Search account videos"
|
||||||
i18n-placeholder placeholder="Search account videos"
|
i18n-placeholder placeholder="Search account videos"
|
||||||
></simple-search-input>
|
></my-simple-search-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<router-outlet (activate)="onOutletLoaded($event)"></router-outlet>
|
<router-outlet (activate)="onOutletLoaded($event)"></router-outlet>
|
||||||
|
|
|
@ -72,7 +72,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
||||||
]))
|
]))
|
||||||
)
|
)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: videoChannels => this.videoChannels = videoChannels.data,
|
next: videoChannels => {
|
||||||
|
this.videoChannels = videoChannels.data
|
||||||
|
},
|
||||||
|
|
||||||
error: err => this.notifier.error(err.message)
|
error: err => this.notifier.error(err.message)
|
||||||
})
|
})
|
||||||
|
@ -176,7 +178,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
||||||
if (user.hasRight(UserRight.MANAGE_USERS)) {
|
if (user.hasRight(UserRight.MANAGE_USERS)) {
|
||||||
this.userService.getUser(account.userId)
|
this.userService.getUser(account.userId)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: accountUser => this.accountUser = accountUser,
|
next: accountUser => {
|
||||||
|
this.accountUser = accountUser
|
||||||
|
},
|
||||||
|
|
||||||
error: err => this.notifier.error(err.message)
|
error: err => this.notifier.error(err.message)
|
||||||
})
|
})
|
||||||
|
@ -209,6 +213,8 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
||||||
itemsPerPage: 0
|
itemsPerPage: 0
|
||||||
},
|
},
|
||||||
sort: '-publishedAt'
|
sort: '-publishedAt'
|
||||||
}).subscribe(res => this.accountVideosCount = res.total)
|
}).subscribe(res => {
|
||||||
|
this.accountVideosCount = res.total
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
||||||
.pipe(pairwise())
|
.pipe(pairwise())
|
||||||
.subscribe(([ oldValue, newValue ]) => {
|
.subscribe(([ oldValue, newValue ]) => {
|
||||||
if (oldValue !== true && newValue === true) {
|
if (oldValue !== true && newValue === true) {
|
||||||
// tslint:disable:max-line-length
|
/* eslint-disable max-len */
|
||||||
this.signupAlertMessage = $localize`You enabled signup: we automatically enabled the "Block new videos automatically" checkbox of the "Videos" section just below.`
|
this.signupAlertMessage = $localize`You enabled signup: we automatically enabled the "Block new videos automatically" checkbox of the "Videos" section just below.`
|
||||||
|
|
||||||
this.form.patchValue({
|
this.form.patchValue({
|
||||||
|
|
|
@ -277,7 +277,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
// Reload general configuration
|
// Reload general configuration
|
||||||
this.serverService.resetConfig()
|
this.serverService.resetConfig()
|
||||||
.subscribe(config => this.serverConfig = config)
|
.subscribe(config => {
|
||||||
|
this.serverConfig = config
|
||||||
|
})
|
||||||
|
|
||||||
this.updateForm()
|
this.updateForm()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
import { FormGroup } from '@angular/forms'
|
import { FormGroup } from '@angular/forms'
|
||||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
|
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { SortMeta } from 'primeng/api'
|
||||||
import { Component, OnInit, ViewChild } from '@angular/core'
|
import { Component, OnInit, ViewChild } from '@angular/core'
|
||||||
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
|
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
|
||||||
import { InstanceFollowService } from '@app/shared/shared-instance'
|
import { InstanceFollowService } from '@app/shared/shared-instance'
|
||||||
import { BatchDomainsModalComponent } from '@app/shared/shared-moderation'
|
|
||||||
import { ActorFollow } from '@shared/models'
|
import { ActorFollow } from '@shared/models'
|
||||||
import { FollowModalComponent } from './follow-modal.component'
|
import { FollowModalComponent } from './follow-modal.component'
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
|
||||||
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
|
||||||
displayType: VideoRedundanciesTarget = 'my-videos'
|
displayType: VideoRedundanciesTarget = 'my-videos'
|
||||||
|
|
||||||
redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: object, options: object }[] = []
|
redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: any, options: any }[] = []
|
||||||
|
|
||||||
noRedundancies = false
|
noRedundancies = false
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<ng-template pTemplate="header">
|
<ng-template pTemplate="header">
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 40px"></th>
|
<th style="width: 40px;"></th>
|
||||||
<th style="width: 150px;"></th>
|
<th style="width: 150px;"></th>
|
||||||
<th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
|
<th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
|
||||||
<th style="width: 100px;" i18n>Sensitive</th>
|
<th style="width: 100px;" i18n>Sensitive</th>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="table-video-text">
|
<div class="table-video-text">
|
||||||
<div>
|
<div>
|
||||||
<my-global-icon i18n-title title="The video was blocked due to automatic blocking of new videos" *ngIf="videoBlock.type == 2" iconName="robot"></my-global-icon>
|
<my-global-icon i18n-title title="The video was blocked due to automatic blocking of new videos" *ngIf="videoBlock.type === 2" iconName="robot"></my-global-icon>
|
||||||
{{ videoBlock.video.name }}
|
{{ videoBlock.video.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div>
|
<div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div>
|
||||||
|
|
|
@ -28,11 +28,11 @@ export class VideoBlockListComponent extends RestTable implements OnInit {
|
||||||
|
|
||||||
inputFilters: AdvancedInputFilter[] = [
|
inputFilters: AdvancedInputFilter[] = [
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'type:auto' },
|
queryParams: { search: 'type:auto' },
|
||||||
label: $localize`Automatic blocks`
|
label: $localize`Automatic blocks`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'type:manual' },
|
queryParams: { search: 'type:manual' },
|
||||||
label: $localize`Manual blocks`
|
label: $localize`Manual blocks`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -44,11 +44,11 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
|
||||||
|
|
||||||
inputFilters: AdvancedInputFilter[] = [
|
inputFilters: AdvancedInputFilter[] = [
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'local:true' },
|
queryParams: { search: 'local:true' },
|
||||||
label: $localize`Local comments`
|
label: $localize`Local comments`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'local:false' },
|
queryParams: { search: 'local:false' },
|
||||||
label: $localize`Remote comments`
|
label: $localize`Remote comments`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-bar">
|
<div class="search-bar">
|
||||||
<input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." autofocus />
|
<input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." myAutofocus />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="alert alert-info" i18n *ngIf="pluginInstalled">
|
<div class="alert alert-info" i18n *ngIf="pluginInstalled">
|
||||||
|
|
|
@ -117,7 +117,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
|
||||||
private getSetting (name: string) {
|
private getSetting (name: string) {
|
||||||
const settings = this.plugin.settings
|
const settings = this.plugin.settings
|
||||||
|
|
||||||
if (settings && settings[name] !== undefined) return settings[name]
|
if (settings?.[name] !== undefined) return settings[name]
|
||||||
|
|
||||||
const registered = this.registeredSettings.find(r => r.name === name)
|
const registered = this.registeredSettings.find(r => r.name === name)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { Observable } from 'rxjs'
|
import { catchError } from 'rxjs/operators'
|
||||||
import { catchError, map, switchMap } from 'rxjs/operators'
|
|
||||||
import { HttpClient, HttpParams } from '@angular/common/http'
|
import { HttpClient, HttpParams } from '@angular/common/http'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ComponentPagination, RestExtractor, RestService } from '@app/core'
|
import { ComponentPagination, RestExtractor, RestService } from '@app/core'
|
||||||
import { PluginService } from '@app/core/plugins/plugin.service'
|
import { PluginService } from '@app/core/plugins/plugin.service'
|
||||||
import { peertubeTranslate } from '@shared/core-utils/i18n'
|
|
||||||
import {
|
import {
|
||||||
InstallOrUpdatePlugin,
|
InstallOrUpdatePlugin,
|
||||||
ManagePlugin,
|
ManagePlugin,
|
||||||
|
|
|
@ -20,9 +20,9 @@ export class JobService {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getJobs (options: {
|
getJobs (options: {
|
||||||
jobState?: JobStateClient,
|
jobState?: JobStateClient
|
||||||
jobType: JobTypeClient,
|
jobType: JobTypeClient
|
||||||
pagination: RestPagination,
|
pagination: RestPagination
|
||||||
sort: SortMeta
|
sort: SortMeta
|
||||||
}): Observable<ResultList<Job>> {
|
}): Observable<ResultList<Job>> {
|
||||||
const { jobState, jobType, pagination, sort } = options
|
const { jobState, jobType, pagination, sort } = options
|
||||||
|
@ -32,7 +32,7 @@ export class JobService {
|
||||||
|
|
||||||
if (jobType !== 'all') params = params.append('jobType', jobType)
|
if (jobType !== 'all') params = params.append('jobType', jobType)
|
||||||
|
|
||||||
return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState ? jobState : ''}`, { params })
|
return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState || ''}`, { params })
|
||||||
.pipe(
|
.pipe(
|
||||||
map(res => {
|
map(res => {
|
||||||
return this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ])
|
return this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ])
|
||||||
|
|
|
@ -18,9 +18,9 @@ export class LogsService {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getLogs (options: {
|
getLogs (options: {
|
||||||
isAuditLog: boolean,
|
isAuditLog: boolean
|
||||||
startDate: string,
|
startDate: string
|
||||||
level?: LogLevel,
|
level?: LogLevel
|
||||||
endDate?: string
|
endDate?: string
|
||||||
}): Observable<any[]> {
|
}): Observable<any[]> {
|
||||||
const { isAuditLog, startDate } = options
|
const { isAuditLog, startDate } = options
|
||||||
|
|
|
@ -78,7 +78,9 @@ export class UserCreateComponent extends UserEdit implements OnInit {
|
||||||
this.router.navigate([ '/admin/users/list' ])
|
this.router.navigate([ '/admin/users/list' ])
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { HTMLServerConfig, UserAdminFlag, UserRole, VideoResolution } from '@sha
|
||||||
import { SelectOptionsItem } from '../../../../types/select-options-item.model'
|
import { SelectOptionsItem } from '../../../../types/select-options-item.model'
|
||||||
|
|
||||||
@Directive()
|
@Directive()
|
||||||
// tslint:disable-next-line: directive-class-suffix
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||||
export abstract class UserEdit extends FormReactive implements OnInit {
|
export abstract class UserEdit extends FormReactive implements OnInit {
|
||||||
videoQuotaOptions: SelectOptionsItem[] = []
|
videoQuotaOptions: SelectOptionsItem[] = []
|
||||||
videoQuotaDailyOptions: SelectOptionsItem[] = []
|
videoQuotaDailyOptions: SelectOptionsItem[] = []
|
||||||
|
|
|
@ -39,7 +39,9 @@ export class UserPasswordComponent extends FormReactive implements OnInit {
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => this.notifier.success($localize`Password changed for user ${this.username}.`),
|
next: () => this.notifier.success($localize`Password changed for user ${this.username}.`),
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: user => this.onUserFetched(user),
|
next: user => this.onUserFetched(user),
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -91,7 +93,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
|
||||||
this.router.navigate([ '/admin/users/list' ])
|
this.router.navigate([ '/admin/users/list' ])
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +118,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
|
||||||
this.notifier.success($localize`An email asking for password reset has been sent to ${this.user.username}.`)
|
this.notifier.success($localize`An email asking for password reset has been sent to ${this.user.username}.`)
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
|
|
||||||
inputFilters: AdvancedInputFilter[] = [
|
inputFilters: AdvancedInputFilter[] = [
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'banned:true' },
|
queryParams: { search: 'banned:true' },
|
||||||
label: $localize`Banned users`
|
label: $localize`Banned users`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<label i18n for="username">User</label>
|
<label i18n for="username">User</label>
|
||||||
<input
|
<input
|
||||||
type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1"
|
type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1"
|
||||||
formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" autofocus
|
formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" myAutofocus
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ export class MyAccountApplicationsComponent implements OnInit {
|
||||||
|
|
||||||
async renewToken () {
|
async renewToken () {
|
||||||
const res = await this.confirmService.confirm(
|
const res = await this.confirmService.confirm(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
$localize`Renewing the token will disallow previously configured clients from retrieving the feed until they use the new token. Proceed?`,
|
$localize`Renewing the token will disallow previously configured clients from retrieving the feed until they use the new token. Proceed?`,
|
||||||
$localize`Renew token`
|
$localize`Renew token`
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
'new-email': USER_EMAIL_VALIDATOR,
|
'new-email': USER_EMAIL_VALIDATOR,
|
||||||
'password': USER_PASSWORD_VALIDATOR
|
password: USER_PASSWORD_VALIDATOR
|
||||||
})
|
})
|
||||||
|
|
||||||
this.user = this.authService.getUser()
|
this.user = this.authService.getUser()
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { filter } from 'rxjs/operators'
|
import { filter } from 'rxjs/operators'
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { AuthService, Notifier, UserService } from '@app/core'
|
import { AuthService, Notifier, UserService } from '@app/core'
|
||||||
import { USER_CONFIRM_PASSWORD_VALIDATOR, USER_PASSWORD_VALIDATOR, USER_EXISTING_PASSWORD_VALIDATOR } from '@app/shared/form-validators/user-validators'
|
import {
|
||||||
|
USER_CONFIRM_PASSWORD_VALIDATOR,
|
||||||
|
USER_EXISTING_PASSWORD_VALIDATOR,
|
||||||
|
USER_PASSWORD_VALIDATOR
|
||||||
|
} from '@app/shared/form-validators/user-validators'
|
||||||
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { User } from '@shared/models'
|
import { User } from '@shared/models'
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ export class MyAccountDangerZoneComponent {
|
||||||
|
|
||||||
async deleteMe () {
|
async deleteMe () {
|
||||||
const res = await this.confirmService.confirmWithInput(
|
const res = await this.confirmService.confirmWithInput(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
$localize`Are you sure you want to delete your account? This will delete all your data, including channels, videos and comments. Content cached by other servers and other third-parties might make longer to be deleted.`,
|
$localize`Are you sure you want to delete your account? This will delete all your data, including channels, videos and comments. Content cached by other servers and other third-parties might make longer to be deleted.`,
|
||||||
$localize`Type your username to confirm`,
|
$localize`Type your username to confirm`,
|
||||||
this.user.username,
|
this.user.username,
|
||||||
|
|
|
@ -66,7 +66,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -96,7 +98,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
|
||||||
this.router.navigate([ '/my-library', 'video-channels' ])
|
this.router.navigate([ '/my-library', 'video-channels' ])
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { Subject } from 'rxjs'
|
|
||||||
import { tap } from 'rxjs/operators'
|
import { tap } from 'rxjs/operators'
|
||||||
import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core'
|
import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
|
@ -109,9 +108,9 @@ export class MyHistoryComponent implements OnInit, DisableForReuseHook {
|
||||||
this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled })
|
this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled })
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
const message = this.videosHistoryEnabled === true ?
|
const message = this.videosHistoryEnabled === true
|
||||||
$localize`Videos history is enabled` :
|
? $localize`Videos history is enabled`
|
||||||
$localize`Videos history is disabled`
|
: $localize`Videos history is disabled`
|
||||||
|
|
||||||
this.notifier.success(message)
|
this.notifier.success(message)
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,9 @@ export class MyVideoPlaylistCreateComponent extends MyVideoPlaylistEdit implemen
|
||||||
this.router.navigate([ '/my-library', 'video-playlists' ])
|
this.router.navigate([ '/my-library', 'video-playlists' ])
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,8 +145,6 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy {
|
||||||
* we add a delay to prevent unwanted drag&drop.
|
* we add a delay to prevent unwanted drag&drop.
|
||||||
*
|
*
|
||||||
* @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
|
* @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
|
||||||
*
|
|
||||||
* @returns {null|number} Null for no delay, or a number in milliseconds.
|
|
||||||
*/
|
*/
|
||||||
getDragStartDelay (): null | number {
|
getDragStartDelay (): null | number {
|
||||||
if (this.screenService.isInTouchScreen()) {
|
if (this.screenService.isInTouchScreen()) {
|
||||||
|
|
|
@ -72,7 +72,9 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
|
||||||
this.hydrateFormFromPlaylist()
|
this.hydrateFormFromPlaylist()
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +101,9 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
|
||||||
this.router.navigate([ '/my-library', 'video-playlists' ])
|
this.router.navigate([ '/my-library', 'video-playlists' ])
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,9 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
|
||||||
const query = event.query
|
const query = event.query
|
||||||
this.userService.autocomplete(query)
|
this.userService.autocomplete(query)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: usernames => this.usernamePropositions = usernames,
|
next: usernames => {
|
||||||
|
this.usernamePropositions = usernames
|
||||||
|
},
|
||||||
|
|
||||||
error: err => this.notifier.error(err.message)
|
error: err => this.notifier.error(err.message)
|
||||||
})
|
})
|
||||||
|
|
|
@ -49,7 +49,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
|
||||||
|
|
||||||
inputFilters: AdvancedInputFilter[] = [
|
inputFilters: AdvancedInputFilter[] = [
|
||||||
{
|
{
|
||||||
queryParams: { 'search': 'isLive:true' },
|
queryParams: { search: 'isLive:true' },
|
||||||
label: $localize`Only live videos`
|
label: $localize`Only live videos`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component } from '@angular/core'
|
|
||||||
import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
|
import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
|
||||||
|
import { Component } from '@angular/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-custom-stepper',
|
selector: 'my-custom-stepper',
|
||||||
|
@ -14,7 +14,7 @@ export class CustomStepperComponent extends CdkStepper {
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompleted (step: CdkStep) {
|
isCompleted (step: CdkStep) {
|
||||||
return step.stepControl && step.stepControl.dirty && step.stepControl.valid
|
return step.stepControl?.dirty && step.stepControl.valid
|
||||||
}
|
}
|
||||||
|
|
||||||
isAccessible (index: number) {
|
isAccessible (index: number) {
|
||||||
|
|
|
@ -49,8 +49,7 @@ export class RegisterComponent implements OnInit {
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
private hooks: HooksService
|
private hooks: HooksService
|
||||||
) {
|
) { }
|
||||||
}
|
|
||||||
|
|
||||||
get requiresEmailVerification () {
|
get requiresEmailVerification () {
|
||||||
return this.serverConfig.signup.requiresEmailVerification
|
return this.serverConfig.signup.requiresEmailVerification
|
||||||
|
@ -138,11 +137,15 @@ export class RegisterComponent implements OnInit {
|
||||||
this.success = $localize`You are now logged in as ${body.username}!`
|
this.success = $localize`You are now logged in as ${body.username}!`
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => this.error = err.message
|
error: err => {
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { forkJoin, Subscription } from 'rxjs'
|
import { forkJoin, Subscription } from 'rxjs'
|
||||||
import { first, tap } from 'rxjs/operators'
|
import { first } from 'rxjs/operators'
|
||||||
import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
|
import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
|
import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
<a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
|
<my-list-overflow [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
|
@ -64,9 +64,9 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.hotkeys = [
|
this.hotkeys = [
|
||||||
new Hotkey('S', (event: KeyboardEvent): boolean => {
|
new Hotkey('S', (event: KeyboardEvent): boolean => {
|
||||||
this.subscribeButton.subscribed ?
|
if (this.subscribeButton.subscribed) this.subscribeButton.unsubscribe()
|
||||||
this.subscribeButton.unsubscribe() :
|
else this.subscribeButton.subscribe()
|
||||||
this.subscribeButton.subscribe()
|
|
||||||
return false
|
return false
|
||||||
}, undefined, $localize`Subscribe to the account`)
|
}, undefined, $localize`Subscribe to the account`)
|
||||||
]
|
]
|
||||||
|
|
|
@ -73,7 +73,7 @@ export class I18nPrimengCalendarService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTimezone () {
|
getTimezone () {
|
||||||
const gmt = new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1]
|
const gmt = new Date().toString().match(/([A-Z]+[+-][0-9]+)/)[1]
|
||||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
|
||||||
return `${timezone} - ${gmt}`
|
return `${timezone} - ${gmt}`
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
|
||||||
|
|
||||||
const languageId = this.form.value['language']
|
const languageId = this.form.value['language']
|
||||||
|
|
||||||
return languageId && this.existingCaptions.indexOf(languageId) !== -1
|
return languageId && this.existingCaptions.includes(languageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async addCaption () {
|
async addCaption () {
|
||||||
|
|
|
@ -233,7 +233,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
async deleteCaption (caption: VideoCaptionEdit) {
|
async deleteCaption (caption: VideoCaptionEdit) {
|
||||||
// Caption recovers his former state
|
// Caption recovers his former state
|
||||||
if (caption.action && this.initialVideoCaptions.indexOf(caption.language.id) !== -1) {
|
if (caption.action && this.initialVideoCaptions.includes(caption.language.id)) {
|
||||||
caption.action = undefined
|
caption.action = undefined
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
|
import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[dragDrop]'
|
selector: '[myDragDrop]'
|
||||||
})
|
})
|
||||||
export class DragDropDirective {
|
export class DragDropDirective {
|
||||||
@Output() fileDropped = new EventEmitter<FileList>()
|
@Output() fileDropped = new EventEmitter<FileList>()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (fileDropped)="setTorrentFile($event)">
|
<div *ngIf="!hasImportedVideo" class="upload-video-container" myDragDrop (fileDropped)="setTorrentFile($event)">
|
||||||
<div class="first-step-block">
|
<div class="first-step-block">
|
||||||
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { scrollToTop } from '@app/helpers'
|
||||||
import { FormValidatorService } from '@app/shared/shared-forms'
|
import { FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main'
|
import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main'
|
||||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { PeerTubeProblemDocument, ServerErrorCode, VideoPrivacy, VideoUpdate } from '@shared/models'
|
import { PeerTubeProblemDocument, ServerErrorCode, VideoUpdate } from '@shared/models'
|
||||||
import { hydrateFormFromVideo } from '../shared/video-edit-utils'
|
import { hydrateFormFromVideo } from '../shared/video-edit-utils'
|
||||||
import { VideoSend } from './video-send'
|
import { VideoSend } from './video-send'
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, AfterV
|
||||||
}
|
}
|
||||||
|
|
||||||
isTargetUrlValid () {
|
isTargetUrlValid () {
|
||||||
return this.targetUrl && this.targetUrl.match(/https?:\/\//)
|
return this.targetUrl?.match(/https?:\/\//)
|
||||||
}
|
}
|
||||||
|
|
||||||
importVideo () {
|
importVideo () {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { HTMLServerConfig, VideoConstant, VideoPrivacy } from '@shared/models'
|
import { HTMLServerConfig, VideoConstant, VideoPrivacy } from '@shared/models'
|
||||||
|
|
||||||
@Directive()
|
@Directive()
|
||||||
// tslint:disable-next-line: directive-class-suffix
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||||
export abstract class VideoSend extends FormReactive implements OnInit {
|
export abstract class VideoSend extends FormReactive implements OnInit {
|
||||||
userVideoChannels: SelectChannelItem[] = []
|
userVideoChannels: SelectChannelItem[] = []
|
||||||
videoPrivacies: VideoConstant<VideoPrivacy>[] = []
|
videoPrivacies: VideoConstant<VideoPrivacy>[] = []
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (fileDropped)="onFileDropped($event)">
|
<div *ngIf="!isUploadingVideo" class="upload-video-container" myDragDrop (fileDropped)="onFileDropped($event)">
|
||||||
<div class="first-step-block">
|
<div class="first-step-block">
|
||||||
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
|
|
||||||
onUploadVideoOngoing (state: UploadState) {
|
onUploadVideoOngoing (state: UploadState) {
|
||||||
switch (state.status) {
|
switch (state.status) {
|
||||||
case 'error':
|
case 'error': {
|
||||||
const error = state.response?.error || 'Unknow error'
|
const error = state.response?.error || 'Unknow error'
|
||||||
|
|
||||||
this.handleUploadError({
|
this.handleUploadError({
|
||||||
|
@ -143,6 +143,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
url: state.url
|
url: state.url
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
|
||||||
case 'cancelled':
|
case 'cancelled':
|
||||||
this.isUploadingVideo = false
|
this.isUploadingVideo = false
|
||||||
|
@ -323,6 +324,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
const videoQuotaUsedBytes = bytePipes.transform(this.userVideoQuotaUsed, 0)
|
const videoQuotaUsedBytes = bytePipes.transform(this.userVideoQuotaUsed, 0)
|
||||||
const videoQuotaBytes = bytePipes.transform(videoQuota, 0)
|
const videoQuotaBytes = bytePipes.transform(videoQuota, 0)
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
const msg = $localize`Your video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${videoQuotaUsedBytes}, quota: ${videoQuotaBytes})`
|
const msg = $localize`Your video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${videoQuotaUsedBytes}, quota: ${videoQuotaBytes})`
|
||||||
this.notifier.error(msg)
|
this.notifier.error(msg)
|
||||||
|
|
||||||
|
@ -341,6 +343,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
const videoSizeBytes = bytePipes.transform(videofile.size, 0)
|
const videoSizeBytes = bytePipes.transform(videofile.size, 0)
|
||||||
const quotaUsedDailyBytes = bytePipes.transform(this.userVideoQuotaUsedDaily, 0)
|
const quotaUsedDailyBytes = bytePipes.transform(this.userVideoQuotaUsedDaily, 0)
|
||||||
const quotaDailyBytes = bytePipes.transform(videoQuotaDaily, 0)
|
const quotaDailyBytes = bytePipes.transform(videoQuotaDaily, 0)
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
const msg = $localize`Your daily video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${quotaUsedDailyBytes}, quota: ${quotaDailyBytes})`
|
const msg = $localize`Your daily video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${quotaUsedDailyBytes}, quota: ${quotaDailyBytes})`
|
||||||
this.notifier.error(msg)
|
this.notifier.error(msg)
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
update () {
|
update () {
|
||||||
if (this.checkForm() === false
|
if (this.checkForm() === false || this.isUpdatingVideo === true) {
|
||||||
|| this.isUpdatingVideo === true) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Component, ViewEncapsulation } from '@angular/core'
|
||||||
selector: 'my-player-styles',
|
selector: 'my-player-styles',
|
||||||
template: '',
|
template: '',
|
||||||
styleUrls: [ './player-styles.component.scss' ],
|
styleUrls: [ './player-styles.component.scss' ],
|
||||||
// tslint:disable:use-component-view-encapsulation
|
/* eslint-disable @angular-eslint/use-component-view-encapsulation */
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class PlayerStylesComponent {
|
export class PlayerStylesComponent {
|
||||||
|
|
|
@ -91,7 +91,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
|
||||||
// Not initialized yet
|
// Not initialized yet
|
||||||
if (!this.form) return
|
if (!this.form) return
|
||||||
|
|
||||||
if (changes.textValue && changes.textValue.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
|
if (changes.textValue?.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
|
||||||
this.patchTextValue(changes.textValue.currentValue, true)
|
this.patchTextValue(changes.textValue.currentValue, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
class="comment-html"
|
class="comment-html"
|
||||||
[innerHTML]="sanitizedCommentHTML"
|
[innerHTML]="sanitizedCommentHTML"
|
||||||
(timestampClicked)="handleTimestampClicked($event)"
|
(timestampClicked)="handleTimestampClicked($event)"
|
||||||
timestampRouteTransformer
|
myTimestampRouteTransformer
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="comment-actions">
|
<div class="comment-actions">
|
||||||
|
|
|
@ -200,7 +200,11 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
async onWantedToRedraft (commentToRedraft: VideoComment) {
|
async onWantedToRedraft (commentToRedraft: VideoComment) {
|
||||||
const confirm = await this.onWantedToDelete(commentToRedraft, $localize`Delete and re-draft`, $localize`Do you really want to delete and re-draft this comment?`)
|
const confirm = await this.onWantedToDelete(
|
||||||
|
commentToRedraft,
|
||||||
|
$localize`Delete and re-draft`,
|
||||||
|
$localize`Do you really want to delete and re-draft this comment?`
|
||||||
|
)
|
||||||
|
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
this.inReplyToCommentId = commentToRedraft.inReplyToCommentId
|
this.inReplyToCommentId = commentToRedraft.inReplyToCommentId
|
||||||
|
|
|
@ -23,7 +23,7 @@ export class VideoAlertComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasVideoScheduledPublication () {
|
hasVideoScheduledPublication () {
|
||||||
return this.video && this.video.scheduledUpdate !== undefined
|
return this.video?.scheduledUpdate !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
isWaitingForLive () {
|
isWaitingForLive () {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class="video-info-description-html"
|
class="video-info-description-html"
|
||||||
[innerHTML]="videoHTMLDescription"
|
[innerHTML]="videoHTMLDescription"
|
||||||
(timestampClicked)="onTimestampClicked($event)"
|
(timestampClicked)="onTimestampClicked($event)"
|
||||||
timestampRouteTransformer
|
myTimestampRouteTransformer
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
|
<div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class VideoWatchPlaylistComponent {
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
private videoPlaylist: VideoPlaylistService,
|
private videoPlaylist: VideoPlaylistService,
|
||||||
private localStorageService: LocalStorageService,
|
private localStorageService: LocalStorageService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorage: SessionStorageService,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {
|
) {
|
||||||
// defaults to true
|
// defaults to true
|
||||||
|
@ -50,7 +50,7 @@ export class VideoWatchPlaylistComponent {
|
||||||
this.setAutoPlayNextVideoPlaylistSwitchText()
|
this.setAutoPlayNextVideoPlaylistSwitchText()
|
||||||
|
|
||||||
// defaults to false
|
// defaults to false
|
||||||
this.loopPlaylist = this.sessionStorageService.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
|
this.loopPlaylist = this.sessionStorage.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
|
||||||
this.setLoopPlaylistSwitchText()
|
this.setLoopPlaylistSwitchText()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ export class VideoWatchPlaylistComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const found = this.playlistElements.find(e => e.position === position)
|
const found = this.playlistElements.find(e => e.position === position)
|
||||||
if (found && found.video) return found
|
if (found?.video) return found
|
||||||
|
|
||||||
const newPosition = type === 'previous'
|
const newPosition = type === 'previous'
|
||||||
? position - 1
|
? position - 1
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
>
|
>
|
||||||
</my-video-miniature>
|
</my-video-miniature>
|
||||||
|
|
||||||
<hr *ngIf="!playlist && i == 0 && length > 1" />
|
<hr *ngIf="!playlist && i === 0 && length > 1" />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Directive, EventEmitter, HostListener, Output } from '@angular/core'
|
import { Directive, EventEmitter, HostListener, Output } from '@angular/core'
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[timestampRouteTransformer]'
|
selector: '[myTimestampRouteTransformer]'
|
||||||
})
|
})
|
||||||
export class TimestampRouteTransformerDirective {
|
export class TimestampRouteTransformerDirective {
|
||||||
@Output() timestampClicked = new EventEmitter<number>()
|
@Output() timestampClicked = new EventEmitter<number>()
|
||||||
|
|
|
@ -292,6 +292,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
const originUrl = errorBody.originUrl + (window.location.search ?? '')
|
const originUrl = errorBody.originUrl + (window.location.search ?? '')
|
||||||
|
|
||||||
const res = await this.confirmService.confirm(
|
const res = await this.confirmService.confirm(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
$localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
|
$localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
|
||||||
$localize`Redirection`
|
$localize`Redirection`
|
||||||
)
|
)
|
||||||
|
@ -312,7 +313,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
if (!errorMessage) return
|
if (!errorMessage) return
|
||||||
|
|
||||||
// Display a message in the video player instead of a notification
|
// Display a message in the video player instead of a notification
|
||||||
if (errorMessage.indexOf('from xs param') !== -1) {
|
if (errorMessage.includes('from xs param')) {
|
||||||
this.flushPlayer()
|
this.flushPlayer()
|
||||||
this.remoteServerDown = true
|
this.remoteServerDown = true
|
||||||
|
|
||||||
|
@ -466,7 +467,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
if (this.nextVideoUUID) {
|
if (this.nextVideoUUID) {
|
||||||
this.router.navigate([ '/w', this.nextVideoUUID ])
|
this.router.navigate([ '/w', this.nextVideoUUID ])
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,14 +483,14 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private isAutoPlayNext () {
|
private isAutoPlayNext () {
|
||||||
return (
|
return (
|
||||||
(this.user && this.user.autoPlayNextVideo) ||
|
(this.user?.autoPlayNextVideo) ||
|
||||||
this.anonymousUser.autoPlayNextVideo
|
this.anonymousUser.autoPlayNextVideo
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private isPlaylistAutoPlayNext () {
|
private isPlaylistAutoPlayNext () {
|
||||||
return (
|
return (
|
||||||
(this.user && this.user.autoPlayNextVideoPlaylist) ||
|
(this.user?.autoPlayNextVideoPlaylist) ||
|
||||||
this.anonymousUser.autoPlayNextVideoPlaylist
|
this.anonymousUser.autoPlayNextVideoPlaylist
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -508,9 +508,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildPlayerManagerOptions (params: {
|
private buildPlayerManagerOptions (params: {
|
||||||
video: VideoDetails,
|
video: VideoDetails
|
||||||
videoCaptions: VideoCaption[],
|
videoCaptions: VideoCaption[]
|
||||||
urlOptions: CustomizationOptions & { playerMode: PlayerMode },
|
urlOptions: CustomizationOptions & { playerMode: PlayerMode }
|
||||||
user?: AuthUser
|
user?: AuthUser
|
||||||
}) {
|
}) {
|
||||||
const { video, videoCaptions, urlOptions, user } = params
|
const { video, videoCaptions, urlOptions, user } = params
|
||||||
|
@ -573,10 +573,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
language: this.localeId,
|
language: this.localeId,
|
||||||
|
|
||||||
userWatching: user && user.videosHistoryEnabled === true ? {
|
userWatching: user && user.videosHistoryEnabled === true
|
||||||
|
? {
|
||||||
url: this.videoService.getUserWatchingVideoUrl(video.uuid),
|
url: this.videoService.getUserWatchingVideoUrl(video.uuid),
|
||||||
authorizationHeader: this.authService.getRequestHeaderValue()
|
authorizationHeader: this.authService.getRequestHeaderValue()
|
||||||
} : undefined,
|
}
|
||||||
|
: undefined,
|
||||||
|
|
||||||
serverUrl: environment.apiUrl,
|
serverUrl: environment.apiUrl,
|
||||||
|
|
||||||
|
@ -704,9 +706,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
if (this.isUserLoggedIn()) {
|
if (this.isUserLoggedIn()) {
|
||||||
this.hotkeys = this.hotkeys.concat([
|
this.hotkeys = this.hotkeys.concat([
|
||||||
new Hotkey('shift+s', () => {
|
new Hotkey('shift+s', () => {
|
||||||
this.subscribeButton.isSubscribedToAll()
|
if (this.subscribeButton.isSubscribedToAll()) this.subscribeButton.unsubscribe()
|
||||||
? this.subscribeButton.unsubscribe()
|
else this.subscribeButton.subscribe()
|
||||||
: this.subscribeButton.subscribe()
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}, undefined, $localize`Subscribe to the account`)
|
}, undefined, $localize`Subscribe to the account`)
|
||||||
|
|
|
@ -15,7 +15,7 @@ interface VideoTrendingHeaderItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'video-trending-title-page',
|
selector: 'my-video-trending-title-page',
|
||||||
styleUrls: [ './video-trending-header.component.scss' ],
|
styleUrls: [ './video-trending-header.component.scss' ],
|
||||||
templateUrl: './video-trending-header.component.html'
|
templateUrl: './video-trending-header.component.html'
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
|
||||||
import { immutableAssign } from '@app/helpers'
|
import { immutableAssign } from '@app/helpers'
|
||||||
import { VideoService } from '@app/shared/shared-main'
|
import { VideoService } from '@app/shared/shared-main'
|
||||||
import { AbstractVideoList } from '@app/shared/shared-video-miniature'
|
import { AbstractVideoList } from '@app/shared/shared-video-miniature'
|
||||||
import { UserRight, VideoFilter, VideoSortField } from '@shared/models'
|
import { VideoFilter, VideoSortField } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-videos-local',
|
selector: 'my-videos-local',
|
||||||
|
|
|
@ -243,7 +243,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
// Inject JS
|
// Inject JS
|
||||||
if (this.serverConfig.instance.customizations.javascript) {
|
if (this.serverConfig.instance.customizations.javascript) {
|
||||||
try {
|
try {
|
||||||
// tslint:disable:no-eval
|
/* eslint-disable no-eval */
|
||||||
eval(this.serverConfig.instance.customizations.javascript)
|
eval(this.serverConfig.instance.customizations.javascript)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Cannot eval custom JavaScript.', err)
|
console.error('Cannot eval custom JavaScript.', err)
|
||||||
|
|
|
@ -206,7 +206,9 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
||||||
this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
|
this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
|
||||||
.pipe(
|
.pipe(
|
||||||
map(res => this.handleRefreshToken(res)),
|
map(res => this.handleRefreshToken(res)),
|
||||||
tap(() => { this.refreshingTokenObservable = null }),
|
tap(() => {
|
||||||
|
this.refreshingTokenObservable = null
|
||||||
|
}),
|
||||||
catchError(err => {
|
catchError(err => {
|
||||||
this.refreshingTokenObservable = null
|
this.refreshingTokenObservable = null
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ export class MenuService {
|
||||||
// On touch screens, lock body scroll and display content overlay when memu is opened
|
// On touch screens, lock body scroll and display content overlay when memu is opened
|
||||||
if (this.isMenuDisplayed) {
|
if (this.isMenuDisplayed) {
|
||||||
document.body.classList.add('menu-open')
|
document.body.classList.add('menu-open')
|
||||||
this.screenService.onFingerSwipe('left', () => { this.setMenuDisplay(false) })
|
this.screenService.onFingerSwipe('left', () => this.setMenuDisplay(false))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,7 @@ export class HooksService {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapObsFun
|
wrapObsFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
|
||||||
<P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
|
|
||||||
(fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
|
(fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
|
||||||
return from(this.pluginService.ensurePluginsAreLoaded(scope))
|
return from(this.pluginService.ensurePluginsAreLoaded(scope))
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -38,8 +37,7 @@ export class HooksService {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async wrapFun
|
async wrapFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
|
||||||
<P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
|
|
||||||
(fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
|
(fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
|
||||||
await this.pluginService.ensurePluginsAreLoaded(scope)
|
await this.pluginService.ensurePluginsAreLoaded(scope)
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ export class PluginService implements ClientHook {
|
||||||
if (!this.authService.isLoggedIn()) return undefined
|
if (!this.authService.isLoggedIn()) return undefined
|
||||||
|
|
||||||
const value = this.authService.getRequestHeaderValue()
|
const value = this.authService.getRequestHeaderValue()
|
||||||
return { 'Authorization': value }
|
return { Authorization: value }
|
||||||
},
|
},
|
||||||
|
|
||||||
notifier: {
|
notifier: {
|
||||||
|
@ -198,10 +198,10 @@ export class PluginService implements ClientHook {
|
||||||
},
|
},
|
||||||
|
|
||||||
showModal: (input: {
|
showModal: (input: {
|
||||||
title: string,
|
title: string
|
||||||
content: string,
|
content: string
|
||||||
close?: boolean,
|
close?: boolean
|
||||||
cancel?: { value: string, action?: () => void },
|
cancel?: { value: string, action?: () => void }
|
||||||
confirm?: { value: string, action?: () => void }
|
confirm?: { value: string, action?: () => void }
|
||||||
}) => {
|
}) => {
|
||||||
this.zone.run(() => this.customModal.show(input))
|
this.zone.run(() => this.customModal.show(input))
|
||||||
|
|
|
@ -156,7 +156,7 @@ export class MarkdownService {
|
||||||
if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ])
|
if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ])
|
||||||
else token.attrs[relIndex][1] = 'noopener noreferrer'
|
else token.attrs[relIndex][1] = 'noopener noreferrer'
|
||||||
|
|
||||||
// pass token to default renderer.
|
// pass token to default renderer.*
|
||||||
return defaultRender(tokens, index, options, env, self)
|
return defaultRender(tokens, index, options, env, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ export class MarkdownService {
|
||||||
private avoidTruncatedTags (html: string) {
|
private avoidTruncatedTags (html: string) {
|
||||||
return html.replace(/\*\*?([^*]+)$/, '$1')
|
return html.replace(/\*\*?([^*]+)$/, '$1')
|
||||||
.replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...')
|
.replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...')
|
||||||
.replace(/\[[^\]]+\]\(([^\)]+)$/m, '$1')
|
.replace(/\[[^\]]+\]\(([^)]+)$/m, '$1')
|
||||||
.replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>')
|
.replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,16 @@ export class RestExtractor {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
applyToResultListData <T> (result: ResultList<T>, fun: Function, additionalArgs?: any[]): ResultList<T> {
|
applyToResultListData <T, A, U> (
|
||||||
|
result: ResultList<T>,
|
||||||
|
fun: (data: T, ...args: A[]) => U,
|
||||||
|
additionalArgs: A[] = []
|
||||||
|
): ResultList<U> {
|
||||||
const data: T[] = result.data
|
const data: T[] = result.data
|
||||||
const newData: T[] = []
|
|
||||||
|
|
||||||
data.forEach(d => newData.push(fun.apply(this, [ d ].concat(additionalArgs))))
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total: result.total,
|
total: result.total,
|
||||||
data: newData
|
data: data.map(d => fun.apply(this, [ d, ...additionalArgs ]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +30,10 @@ export class RestExtractor {
|
||||||
return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ])
|
return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ])
|
||||||
}
|
}
|
||||||
|
|
||||||
convertDateToHuman (target: { [ id: string ]: string }, fieldsToConvert: string[]) {
|
convertDateToHuman (target: any, fieldsToConvert: string[]) {
|
||||||
fieldsToConvert.forEach(field => target[field] = dateToHuman(target[field]))
|
fieldsToConvert.forEach(field => {
|
||||||
|
target[field] = dateToHuman(target[field])
|
||||||
|
})
|
||||||
|
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
@ -46,7 +49,7 @@ export class RestExtractor {
|
||||||
errorMessage = err.error
|
errorMessage = err.error
|
||||||
} else if (err.status !== undefined) {
|
} else if (err.status !== undefined) {
|
||||||
// A server-side error occurred.
|
// A server-side error occurred.
|
||||||
if (err.error && err.error.errors) {
|
if (err.error?.errors) {
|
||||||
const errors = err.error.errors
|
const errors = err.error.errors
|
||||||
const errorsArray: string[] = []
|
const errorsArray: string[] = []
|
||||||
|
|
||||||
|
@ -55,9 +58,10 @@ export class RestExtractor {
|
||||||
})
|
})
|
||||||
|
|
||||||
errorMessage = errorsArray.join('. ')
|
errorMessage = errorsArray.join('. ')
|
||||||
} else if (err.error && err.error.error) {
|
} else if (err.error?.error) {
|
||||||
errorMessage = err.error.error
|
errorMessage = err.error.error
|
||||||
} else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
|
} else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
|
errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
|
||||||
} else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
|
} else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
|
||||||
const secondsLeft = err.headers.get('retry-after')
|
const secondsLeft = err.headers.get('retry-after')
|
||||||
|
@ -71,7 +75,7 @@ export class RestExtractor {
|
||||||
errorMessage = $localize`Server error. Please retry later.`
|
errorMessage = $localize`Server error. Please retry later.`
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage = errorMessage ? errorMessage : 'Unknown error.'
|
errorMessage = errorMessage || 'Unknown error.'
|
||||||
console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`)
|
console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`)
|
||||||
} else {
|
} else {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
@ -93,7 +97,7 @@ export class RestExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) {
|
redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) {
|
||||||
if (obj && obj.status && status.indexOf(obj.status) !== -1) {
|
if (obj?.status && status.includes(obj.status)) {
|
||||||
// Do not use redirectService to avoid circular dependencies
|
// Do not use redirectService to avoid circular dependencies
|
||||||
this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true })
|
this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
|
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomReuseStrategy implements RouteReuseStrategy {
|
export class CustomReuseStrategy implements RouteReuseStrategy {
|
||||||
|
@ -78,6 +78,6 @@ export class CustomReuseStrategy implements RouteReuseStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private isReuseEnabled (route: ActivatedRouteSnapshot) {
|
private isReuseEnabled (route: ActivatedRouteSnapshot) {
|
||||||
return route.data.reuse && route.data.reuse.enabled && route.queryParams[ 'a-state' ]
|
return route.data.reuse?.enabled && route.queryParams['a-state']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,33 +17,43 @@ abstract class MenuGuard implements CanActivate, CanDeactivate<any> {
|
||||||
if (!this.screen.isInMobileView() && this.screen.isInMediumView()) {
|
if (!this.screen.isInMobileView() && this.screen.isInMediumView()) {
|
||||||
this.menu.setMenuDisplay(this.display)
|
this.menu.setMenuDisplay(this.display)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpenMenuGuard extends MenuGuard {
|
export class OpenMenuGuard extends MenuGuard {
|
||||||
constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) }
|
constructor (menu: MenuService, screen: ScreenService) {
|
||||||
|
super(menu, screen, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpenMenuAlwaysGuard extends MenuGuard {
|
export class OpenMenuAlwaysGuard extends MenuGuard {
|
||||||
constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) }
|
constructor (menu: MenuService, screen: ScreenService) {
|
||||||
|
super(menu, screen, true)
|
||||||
|
}
|
||||||
|
|
||||||
canActivate (): boolean {
|
canActivate (): boolean {
|
||||||
this.menu.setMenuDisplay(this.display)
|
this.menu.setMenuDisplay(this.display)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CloseMenuGuard extends MenuGuard {
|
export class CloseMenuGuard extends MenuGuard {
|
||||||
constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) }
|
constructor (menu: MenuService, screen: ScreenService) {
|
||||||
|
super(menu, screen, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CloseMenuAlwaysGuard extends MenuGuard {
|
export class CloseMenuAlwaysGuard extends MenuGuard {
|
||||||
constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) }
|
constructor (menu: MenuService, screen: ScreenService) {
|
||||||
|
super(menu, screen, false)
|
||||||
|
}
|
||||||
|
|
||||||
canActivate (): boolean {
|
canActivate (): boolean {
|
||||||
this.menu.setMenuDisplay(this.display)
|
this.menu.setMenuDisplay(this.display)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot } from '@angular/router'
|
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild } from '@angular/router'
|
||||||
import { MetaService } from './meta.service'
|
import { MetaService } from './meta.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Injectable } from '@angular/core'
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PreloadSelectedModulesList implements PreloadingStrategy {
|
export class PreloadSelectedModulesList implements PreloadingStrategy {
|
||||||
|
|
||||||
preload (route: Route, load: Function): Observable<any> {
|
preload (route: Route, load: () => Observable<any>): Observable<any> {
|
||||||
if (!route.data || !route.data.preload) return ofObservable(null)
|
if (!route.data || !route.data.preload) return ofObservable(null)
|
||||||
|
|
||||||
if (typeof route.data.preload === 'number') {
|
if (typeof route.data.preload === 'number') {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { Injectable } from '@angular/core'
|
|
||||||
import { HttpClient } from '@angular/common/http'
|
|
||||||
import { environment } from '../../../environments/environment'
|
|
||||||
import { AuthService } from '../auth'
|
|
||||||
import { ScopedToken } from '@shared/models/users/user-scoped-token'
|
|
||||||
import { catchError } from 'rxjs/operators'
|
import { catchError } from 'rxjs/operators'
|
||||||
|
import { HttpClient } from '@angular/common/http'
|
||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ScopedToken } from '@shared/models/users/user-scoped-token'
|
||||||
|
import { environment } from '../../../environments/environment'
|
||||||
import { RestExtractor } from '../rest'
|
import { RestExtractor } from '../rest'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http'
|
||||||
import { Inject, Injectable, LOCALE_ID } from '@angular/core'
|
import { Inject, Injectable, LOCALE_ID } from '@angular/core'
|
||||||
import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
|
import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
|
||||||
import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
|
import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
|
||||||
import { HTMLServerConfig, SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
|
import { HTMLServerConfig, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -96,7 +96,7 @@ export class ThemeService {
|
||||||
const links = document.getElementsByTagName('link')
|
const links = document.getElementsByTagName('link')
|
||||||
for (let i = 0; i < links.length; i++) {
|
for (let i = 0; i < links.length; i++) {
|
||||||
const link = links[i]
|
const link = links[i]
|
||||||
if (link.getAttribute('rel').indexOf('style') !== -1 && link.getAttribute('title')) {
|
if (link.getAttribute('rel').includes('style') && link.getAttribute('title')) {
|
||||||
link.disabled = link.getAttribute('title') !== name
|
link.disabled = link.getAttribute('title') !== name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ export class SearchTypeaheadComponent implements OnInit, AfterViewChecked, OnDes
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadUserLanguagesIfNeeded (queryParams: any) {
|
private loadUserLanguagesIfNeeded (queryParams: any) {
|
||||||
if (queryParams && queryParams.languageOneOf) return of(queryParams)
|
if (queryParams?.languageOneOf) return of(queryParams)
|
||||||
|
|
||||||
return this.authService.userInformationLoaded
|
return this.authService.userInformationLoaded
|
||||||
.pipe(
|
.pipe(
|
||||||
|
|
|
@ -54,50 +54,50 @@ export default [
|
||||||
'€',
|
'€',
|
||||||
'euro',
|
'euro',
|
||||||
{
|
{
|
||||||
'ARS': ['$AR', '$'],
|
ARS: [ '$AR', '$' ],
|
||||||
'AUD': ['$AU', '$'],
|
AUD: [ '$AU', '$' ],
|
||||||
'BEF': ['FB'],
|
BEF: [ 'FB' ],
|
||||||
'BMD': ['$BM', '$'],
|
BMD: [ '$BM', '$' ],
|
||||||
'BND': ['$BN', '$'],
|
BND: [ '$BN', '$' ],
|
||||||
'BZD': ['$BZ', '$'],
|
BZD: [ '$BZ', '$' ],
|
||||||
'CAD': ['$CA', '$'],
|
CAD: [ '$CA', '$' ],
|
||||||
'CLP': ['$CL', '$'],
|
CLP: [ '$CL', '$' ],
|
||||||
'CNY': [u, '¥'],
|
CNY: [ u, '¥' ],
|
||||||
'COP': ['$CO', '$'],
|
COP: [ '$CO', '$' ],
|
||||||
'CYP': ['£CY'],
|
CYP: [ '£CY' ],
|
||||||
'EGP': [u, '£E'],
|
EGP: [ u, '£E' ],
|
||||||
'FJD': ['$FJ', '$'],
|
FJD: [ '$FJ', '$' ],
|
||||||
'FKP': ['£FK', '£'],
|
FKP: [ '£FK', '£' ],
|
||||||
'FRF': ['F'],
|
FRF: [ 'F' ],
|
||||||
'GBP': ['£GB', '£'],
|
GBP: [ '£GB', '£' ],
|
||||||
'GIP': ['£GI', '£'],
|
GIP: [ '£GI', '£' ],
|
||||||
'HKD': [u, '$'],
|
HKD: [ u, '$' ],
|
||||||
'IEP': ['£IE'],
|
IEP: [ '£IE' ],
|
||||||
'ILP': ['£IL'],
|
ILP: [ '£IL' ],
|
||||||
'ITL': ['₤IT'],
|
ITL: [ '₤IT' ],
|
||||||
'JPY': [u, '¥'],
|
JPY: [ u, '¥' ],
|
||||||
'KMF': [u, 'FC'],
|
KMF: [ u, 'FC' ],
|
||||||
'LBP': ['£LB', '£L'],
|
LBP: [ '£LB', '£L' ],
|
||||||
'MTP': ['£MT'],
|
MTP: [ '£MT' ],
|
||||||
'MXN': ['$MX', '$'],
|
MXN: [ '$MX', '$' ],
|
||||||
'NAD': ['$NA', '$'],
|
NAD: [ '$NA', '$' ],
|
||||||
'NIO': [u, '$C'],
|
NIO: [ u, '$C' ],
|
||||||
'NZD': ['$NZ', '$'],
|
NZD: [ '$NZ', '$' ],
|
||||||
'RHD': ['$RH'],
|
RHD: [ '$RH' ],
|
||||||
'RON': [u, 'L'],
|
RON: [ u, 'L' ],
|
||||||
'RWF': [u, 'FR'],
|
RWF: [ u, 'FR' ],
|
||||||
'SBD': ['$SB', '$'],
|
SBD: [ '$SB', '$' ],
|
||||||
'SGD': ['$SG', '$'],
|
SGD: [ '$SG', '$' ],
|
||||||
'SRD': ['$SR', '$'],
|
SRD: [ '$SR', '$' ],
|
||||||
'TOP': [u, '$T'],
|
TOP: [ u, '$T' ],
|
||||||
'TTD': ['$TT', '$'],
|
TTD: [ '$TT', '$' ],
|
||||||
'TWD': [u, 'NT$'],
|
TWD: [ u, 'NT$' ],
|
||||||
'USD': ['$US', '$'],
|
USD: [ '$US', '$' ],
|
||||||
'UYU': ['$UY', '$'],
|
UYU: [ '$UY', '$' ],
|
||||||
'WST': ['$WS'],
|
WST: [ '$WS' ],
|
||||||
'XCD': [u, '$'],
|
XCD: [ u, '$' ],
|
||||||
'XPF': ['FCFP'],
|
XPF: [ 'FCFP' ],
|
||||||
'ZMW': [u, 'Kw']
|
ZMW: [ u, 'Kw' ]
|
||||||
},
|
},
|
||||||
'ltr',
|
'ltr',
|
||||||
plural
|
plural
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { AuthService } from '../core/auth'
|
||||||
// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
|
// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
|
||||||
function getParameterByName (name: string, url: string) {
|
function getParameterByName (name: string, url: string) {
|
||||||
if (!url) url = window.location.href
|
if (!url) url = window.location.href
|
||||||
name = name.replace(/[\[\]]/g, '\\$&')
|
name = name.replace(/[[\]]/g, '\\$&')
|
||||||
|
|
||||||
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
|
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
|
||||||
const results = regex.exec(url)
|
const results = regex.exec(url)
|
||||||
|
|
|
@ -22,10 +22,10 @@ export class CustomModalComponent {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
show (input: {
|
show (input: {
|
||||||
title: string,
|
title: string
|
||||||
content: string,
|
content: string
|
||||||
close?: boolean,
|
close?: boolean
|
||||||
cancel?: { value: string, action?: () => void },
|
cancel?: { value: string, action?: () => void }
|
||||||
confirm?: { value: string, action?: () => void }
|
confirm?: { value: string, action?: () => void }
|
||||||
}) {
|
}) {
|
||||||
if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) {
|
if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) {
|
||||||
|
|
|
@ -4,26 +4,26 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const ABUSE_REASON_VALIDATOR: BuildFormValidator = {
|
export const ABUSE_REASON_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Report reason is required.`,
|
required: $localize`Report reason is required.`,
|
||||||
'minlength': $localize`Report reason must be at least 2 characters long.`,
|
minlength: $localize`Report reason must be at least 2 characters long.`,
|
||||||
'maxlength': $localize`Report reason cannot be more than 3000 characters long.`
|
maxlength: $localize`Report reason cannot be more than 3000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ABUSE_MODERATION_COMMENT_VALIDATOR: BuildFormValidator = {
|
export const ABUSE_MODERATION_COMMENT_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Moderation comment is required.`,
|
required: $localize`Moderation comment is required.`,
|
||||||
'minlength': $localize`Moderation comment must be at least 2 characters long.`,
|
minlength: $localize`Moderation comment must be at least 2 characters long.`,
|
||||||
'maxlength': $localize`Moderation comment cannot be more than 3000 characters long.`
|
maxlength: $localize`Moderation comment cannot be more than 3000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ABUSE_MESSAGE_VALIDATOR: BuildFormValidator = {
|
export const ABUSE_MESSAGE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Abuse message is required.`,
|
required: $localize`Abuse message is required.`,
|
||||||
'minlength': $localize`Abuse message must be at least 2 characters long.`,
|
minlength: $localize`Abuse message must be at least 2 characters long.`,
|
||||||
'maxlength': $localize`Abuse message cannot be more than 3000 characters long.`
|
maxlength: $localize`Abuse message cannot be more than 3000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,118 +4,118 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const INSTANCE_NAME_VALIDATOR: BuildFormValidator = {
|
export const INSTANCE_NAME_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Instance name is required.`
|
required: $localize`Instance name is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const INSTANCE_SHORT_DESCRIPTION_VALIDATOR: BuildFormValidator = {
|
export const INSTANCE_SHORT_DESCRIPTION_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.max(250) ],
|
VALIDATORS: [ Validators.max(250) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'max': $localize`Short description should not be longer than 250 characters.`
|
max: $localize`Short description should not be longer than 250 characters.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SERVICES_TWITTER_USERNAME_VALIDATOR: BuildFormValidator = {
|
export const SERVICES_TWITTER_USERNAME_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Twitter username is required.`
|
required: $localize`Twitter username is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CACHE_PREVIEWS_SIZE_VALIDATOR: BuildFormValidator = {
|
export const CACHE_PREVIEWS_SIZE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Previews cache size is required.`,
|
required: $localize`Previews cache size is required.`,
|
||||||
'min': $localize`Previews cache size must be greater than 1.`,
|
min: $localize`Previews cache size must be greater than 1.`,
|
||||||
'pattern': $localize`Previews cache size must be a number.`
|
pattern: $localize`Previews cache size must be a number.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CACHE_CAPTIONS_SIZE_VALIDATOR: BuildFormValidator = {
|
export const CACHE_CAPTIONS_SIZE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Captions cache size is required.`,
|
required: $localize`Captions cache size is required.`,
|
||||||
'min': $localize`Captions cache size must be greater than 1.`,
|
min: $localize`Captions cache size must be greater than 1.`,
|
||||||
'pattern': $localize`Captions cache size must be a number.`
|
pattern: $localize`Captions cache size must be a number.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SIGNUP_LIMIT_VALIDATOR: BuildFormValidator = {
|
export const SIGNUP_LIMIT_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1), Validators.pattern('-?[0-9]+') ],
|
VALIDATORS: [ Validators.required, Validators.min(-1), Validators.pattern('-?[0-9]+') ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Signup limit is required.`,
|
required: $localize`Signup limit is required.`,
|
||||||
'min': $localize`Signup limit must be greater than 1. Use -1 to disable it.`,
|
min: $localize`Signup limit must be greater than 1. Use -1 to disable it.`,
|
||||||
'pattern': $localize`Signup limit must be a number.`
|
pattern: $localize`Signup limit must be a number.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SIGNUP_MINIMUM_AGE_VALIDATOR: BuildFormValidator = {
|
export const SIGNUP_MINIMUM_AGE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Signup minimum age is required.`,
|
required: $localize`Signup minimum age is required.`,
|
||||||
'min': $localize`Signup minimum age must be greater than 1.`,
|
min: $localize`Signup minimum age must be greater than 1.`,
|
||||||
'pattern': $localize`Signup minimum age must be a number.`
|
pattern: $localize`Signup minimum age must be a number.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ADMIN_EMAIL_VALIDATOR: BuildFormValidator = {
|
export const ADMIN_EMAIL_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.email ],
|
VALIDATORS: [ Validators.required, Validators.email ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Admin email is required.`,
|
required: $localize`Admin email is required.`,
|
||||||
'email': $localize`Admin email must be valid.`
|
email: $localize`Admin email must be valid.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = {
|
export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(0) ],
|
VALIDATORS: [ Validators.required, Validators.min(0) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Transcoding threads is required.`,
|
required: $localize`Transcoding threads is required.`,
|
||||||
'min': $localize`Transcoding threads must be greater or equal to 0.`
|
min: $localize`Transcoding threads must be greater or equal to 0.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_LIVE_DURATION_VALIDATOR: BuildFormValidator = {
|
export const MAX_LIVE_DURATION_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Max live duration is required.`,
|
required: $localize`Max live duration is required.`,
|
||||||
'min': $localize`Max live duration should be greater or equal to -1.`
|
min: $localize`Max live duration should be greater or equal to -1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_INSTANCE_LIVES_VALIDATOR: BuildFormValidator = {
|
export const MAX_INSTANCE_LIVES_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Max instance lives is required.`,
|
required: $localize`Max instance lives is required.`,
|
||||||
'min': $localize`Max instance lives should be greater or equal to -1.`
|
min: $localize`Max instance lives should be greater or equal to -1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_USER_LIVES_VALIDATOR: BuildFormValidator = {
|
export const MAX_USER_LIVES_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Max user lives is required.`,
|
required: $localize`Max user lives is required.`,
|
||||||
'min': $localize`Max user lives should be greater or equal to -1.`
|
min: $localize`Max user lives should be greater or equal to -1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CONCURRENCY_VALIDATOR: BuildFormValidator = {
|
export const CONCURRENCY_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(1) ],
|
VALIDATORS: [ Validators.required, Validators.min(1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Concurrency is required.`,
|
required: $localize`Concurrency is required.`,
|
||||||
'min': $localize`Concurrency should be greater or equal to 1.`
|
min: $localize`Concurrency should be greater or equal to 1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const INDEX_URL_VALIDATOR: BuildFormValidator = {
|
export const INDEX_URL_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.pattern(/^https:\/\//) ],
|
VALIDATORS: [ Validators.pattern(/^https:\/\//) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'pattern': $localize`Index URL should be a URL`
|
pattern: $localize`Index URL should be a URL`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SEARCH_INDEX_URL_VALIDATOR: BuildFormValidator = {
|
export const SEARCH_INDEX_URL_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.pattern(/^https?:\/\//) ],
|
VALIDATORS: [ Validators.pattern(/^https?:\/\//) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'pattern': $localize`Search index URL should be a URL`
|
pattern: $localize`Search index URL should be a URL`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ValidatorFn } from '@angular/forms'
|
import { ValidatorFn } from '@angular/forms'
|
||||||
|
|
||||||
export type BuildFormValidator = {
|
export type BuildFormValidator = {
|
||||||
VALIDATORS: ValidatorFn[],
|
VALIDATORS: ValidatorFn[]
|
||||||
MESSAGES: { [ name: string ]: string }
|
MESSAGES: { [ name: string ]: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export function validateHost (value: string) {
|
export function validateHost (value: string) {
|
||||||
// Thanks to http://stackoverflow.com/a/106223
|
// Thanks to http://stackoverflow.com/a/106223
|
||||||
const HOST_REGEXP = new RegExp(
|
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])$'
|
'^(([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)
|
return HOST_REGEXP.test(value)
|
||||||
|
@ -32,7 +32,7 @@ const validHosts: ValidatorFn = (control: AbstractControl) => {
|
||||||
if (errors.length === 0) return null
|
if (errors.length === 0) return null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'validHosts': {
|
validHosts: {
|
||||||
reason: 'invalid',
|
reason: 'invalid',
|
||||||
value: errors.join('. ') + '.'
|
value: errors.join('. ') + '.'
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ const validHostsOrHandles: ValidatorFn = (control: AbstractControl) => {
|
||||||
if (errors.length === 0) return null
|
if (errors.length === 0) return null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'validHostsOrHandles': {
|
validHostsOrHandles: {
|
||||||
reason: 'invalid',
|
reason: 'invalid',
|
||||||
value: errors.join('. ') + '.'
|
value: errors.join('. ') + '.'
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ export const unique: ValidatorFn = (control: AbstractControl) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'unique': {
|
unique: {
|
||||||
reason: 'invalid'
|
reason: 'invalid'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,17 +89,17 @@ export const unique: ValidatorFn = (control: AbstractControl) => {
|
||||||
export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = {
|
export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, validHosts, unique ],
|
VALIDATORS: [ Validators.required, validHosts, unique ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Domain is required.`,
|
required: $localize`Domain is required.`,
|
||||||
'validHosts': $localize`Hosts entered are invalid.`,
|
validHosts: $localize`Hosts entered are invalid.`,
|
||||||
'unique': $localize`Hosts entered contain duplicates.`
|
unique: $localize`Hosts entered contain duplicates.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = {
|
export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, validHostsOrHandles, unique ],
|
VALIDATORS: [ Validators.required, validHostsOrHandles, unique ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Domain is required.`,
|
required: $localize`Domain is required.`,
|
||||||
'validHostsOrHandles': $localize`Hosts or handles are invalid.`,
|
validHostsOrHandles: $localize`Hosts or handles are invalid.`,
|
||||||
'unique': $localize`Hosts or handles contain duplicates.`
|
unique: $localize`Hosts or handles contain duplicates.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const FROM_EMAIL_VALIDATOR: BuildFormValidator = {
|
export const FROM_EMAIL_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.email ],
|
VALIDATORS: [ Validators.required, Validators.email ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Email is required.`,
|
required: $localize`Email is required.`,
|
||||||
'email': $localize`Email must be valid.`
|
email: $localize`Email must be valid.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ export const FROM_NAME_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(120)
|
Validators.maxLength(120)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Your name is required.`,
|
required: $localize`Your name is required.`,
|
||||||
'minlength': $localize`Your name must be at least 1 character long.`,
|
minlength: $localize`Your name must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Your name cannot be more than 120 characters long.`
|
maxlength: $localize`Your name cannot be more than 120 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ export const SUBJECT_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(120)
|
Validators.maxLength(120)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`A subject is required.`,
|
required: $localize`A subject is required.`,
|
||||||
'minlength': $localize`The subject must be at least 1 character long.`,
|
minlength: $localize`The subject must be at least 1 character long.`,
|
||||||
'maxlength': $localize`The subject cannot be more than 120 characters long.`
|
maxlength: $localize`The subject cannot be more than 120 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ export const BODY_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(5000)
|
Validators.maxLength(5000)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`A message is required.`,
|
required: $localize`A message is required.`,
|
||||||
'minlength': $localize`The message must be at least 3 characters long.`,
|
minlength: $localize`The message must be at least 3 characters long.`,
|
||||||
'maxlength': $localize`The message cannot be more than 5000 characters long.`
|
maxlength: $localize`The message cannot be more than 5000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ export const LOGIN_USERNAME_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Username is required.`
|
required: $localize`Username is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,6 @@ export const LOGIN_PASSWORD_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Password is required.`
|
required: $localize`Password is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ export const RESET_PASSWORD_CONFIRM_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Confirmation of the password is required.`
|
required: $localize`Confirmation of the password is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ export const USER_USERNAME_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.pattern(new RegExp(`^${USER_USERNAME_REGEX_CHARACTERS}*$`))
|
Validators.pattern(new RegExp(`^${USER_USERNAME_REGEX_CHARACTERS}*$`))
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Username is required.`,
|
required: $localize`Username is required.`,
|
||||||
'minlength': $localize`Username must be at least 1 character long.`,
|
minlength: $localize`Username must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Username cannot be more than 50 characters long.`,
|
maxlength: $localize`Username cannot be more than 50 characters long.`,
|
||||||
'pattern': $localize`Username should be lowercase alphanumeric; dots and underscores are allowed.`
|
pattern: $localize`Username should be lowercase alphanumeric; dots and underscores are allowed.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,18 +26,18 @@ export const USER_CHANNEL_NAME_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.pattern(/^[a-z0-9][a-z0-9._]*$/)
|
Validators.pattern(/^[a-z0-9][a-z0-9._]*$/)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Channel name is required.`,
|
required: $localize`Channel name is required.`,
|
||||||
'minlength': $localize`Channel name must be at least 1 character long.`,
|
minlength: $localize`Channel name must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Channel name cannot be more than 50 characters long.`,
|
maxlength: $localize`Channel name cannot be more than 50 characters long.`,
|
||||||
'pattern': $localize`Channel name should be lowercase, and can contain only alphanumeric characters, dots and underscores.`
|
pattern: $localize`Channel name should be lowercase, and can contain only alphanumeric characters, dots and underscores.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_EMAIL_VALIDATOR: BuildFormValidator = {
|
export const USER_EMAIL_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.email ],
|
VALIDATORS: [ Validators.required, Validators.email ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Email is required.`,
|
required: $localize`Email is required.`,
|
||||||
'email': $localize`Email must be valid.`
|
email: $localize`Email must be valid.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ export const USER_HANDLE_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.pattern(/@.+/)
|
Validators.pattern(/@.+/)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Handle is required.`,
|
required: $localize`Handle is required.`,
|
||||||
'pattern': $localize`Handle must be valid (eg. chocobozzz@example.com).`
|
pattern: $localize`Handle must be valid (eg. chocobozzz@example.com).`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ export const USER_EXISTING_PASSWORD_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Password is required.`
|
required: $localize`Password is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ export const USER_PASSWORD_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(255)
|
Validators.maxLength(255)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Password is required.`,
|
required: $localize`Password is required.`,
|
||||||
'minlength': $localize`Password must be at least 6 characters long.`,
|
minlength: $localize`Password must be at least 6 characters long.`,
|
||||||
'maxlength': $localize`Password cannot be more than 255 characters long.`
|
maxlength: $localize`Password cannot be more than 255 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,37 +80,37 @@ export const USER_PASSWORD_OPTIONAL_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(255)
|
Validators.maxLength(255)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Password must be at least 6 characters long.`,
|
minlength: $localize`Password must be at least 6 characters long.`,
|
||||||
'maxlength': $localize`Password cannot be more than 255 characters long.`
|
maxlength: $localize`Password cannot be more than 255 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_CONFIRM_PASSWORD_VALIDATOR: BuildFormValidator = {
|
export const USER_CONFIRM_PASSWORD_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [],
|
VALIDATORS: [],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'matchPassword': $localize`The new password and the confirmed password do not correspond.`
|
matchPassword: $localize`The new password and the confirmed password do not correspond.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_VIDEO_QUOTA_VALIDATOR: BuildFormValidator = {
|
export const USER_VIDEO_QUOTA_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Video quota is required.`,
|
required: $localize`Video quota is required.`,
|
||||||
'min': $localize`Quota must be greater than -1.`
|
min: $localize`Quota must be greater than -1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const USER_VIDEO_QUOTA_DAILY_VALIDATOR: BuildFormValidator = {
|
export const USER_VIDEO_QUOTA_DAILY_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
VALIDATORS: [ Validators.required, Validators.min(-1) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Daily upload limit is required.`,
|
required: $localize`Daily upload limit is required.`,
|
||||||
'min': $localize`Daily upload limit must be greater than -1.`
|
min: $localize`Daily upload limit must be greater than -1.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_ROLE_VALIDATOR: BuildFormValidator = {
|
export const USER_ROLE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`User role is required.`
|
required: $localize`User role is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,15 +122,15 @@ export const USER_DESCRIPTION_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(1000)
|
Validators.maxLength(1000)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Description must be at least 3 characters long.`,
|
minlength: $localize`Description must be at least 3 characters long.`,
|
||||||
'maxlength': $localize`Description cannot be more than 1000 characters long.`
|
maxlength: $localize`Description cannot be more than 1000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_TERMS_VALIDATOR: BuildFormValidator = {
|
export const USER_TERMS_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.requiredTrue ],
|
VALIDATORS: [ Validators.requiredTrue ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`You must agree with the instance terms in order to register on it.`
|
required: $localize`You must agree with the instance terms in order to register on it.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,8 +140,8 @@ export const USER_BAN_REASON_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(250)
|
Validators.maxLength(250)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Ban reason must be at least 3 characters long.`,
|
minlength: $localize`Ban reason must be at least 3 characters long.`,
|
||||||
'maxlength': $localize`Ban reason cannot be more than 250 characters long.`
|
maxlength: $localize`Ban reason cannot be more than 250 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,9 +152,9 @@ function buildDisplayNameValidator (required: boolean) {
|
||||||
Validators.maxLength(120)
|
Validators.maxLength(120)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Display name is required.`,
|
required: $localize`Display name is required.`,
|
||||||
'minlength': $localize`Display name must be at least 1 character long.`,
|
minlength: $localize`Display name must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Display name cannot be more than 50 characters long.`
|
maxlength: $localize`Display name cannot be more than 50 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const VIDEO_BLOCK_REASON_VALIDATOR: BuildFormValidator = {
|
export const VIDEO_BLOCK_REASON_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ],
|
VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Block reason must be at least 2 characters long.`,
|
minlength: $localize`Block reason must be at least 2 characters long.`,
|
||||||
'maxlength': $localize`Block reason cannot be more than 300 characters long.`
|
maxlength: $localize`Block reason cannot be more than 300 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const VIDEO_CAPTION_LANGUAGE_VALIDATOR: BuildFormValidator = {
|
export const VIDEO_CAPTION_LANGUAGE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Video caption language is required.`
|
required: $localize`Video caption language is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VIDEO_CAPTION_FILE_VALIDATOR: BuildFormValidator = {
|
export const VIDEO_CAPTION_FILE_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required ],
|
VALIDATORS: [ Validators.required ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Video caption file is required.`
|
required: $localize`Video caption file is required.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ export const VIDEO_CHANNEL_NAME_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: USER_USERNAME_VALIDATOR.VALIDATORS,
|
VALIDATORS: USER_USERNAME_VALIDATOR.VALIDATORS,
|
||||||
|
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Name is required.`,
|
required: $localize`Name is required.`,
|
||||||
'minlength': $localize`Name must be at least 1 character long.`,
|
minlength: $localize`Name must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Name cannot be more than 50 characters long.`,
|
maxlength: $localize`Name cannot be more than 50 characters long.`,
|
||||||
'pattern': $localize`Name should be lowercase alphanumeric; dots and underscores are allowed.`
|
pattern: $localize`Name should be lowercase alphanumeric; dots and underscores are allowed.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ export const VIDEO_CHANNEL_DISPLAY_NAME_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(50)
|
Validators.maxLength(50)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Display name is required.`,
|
required: $localize`Display name is required.`,
|
||||||
'minlength': $localize`Display name must be at least 1 character long.`,
|
minlength: $localize`Display name must be at least 1 character long.`,
|
||||||
'maxlength': $localize`Display name cannot be more than 50 characters long.`
|
maxlength: $localize`Display name cannot be more than 50 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ export const VIDEO_CHANNEL_DESCRIPTION_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(1000)
|
Validators.maxLength(1000)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Description must be at least 3 characters long.`,
|
minlength: $localize`Description must be at least 3 characters long.`,
|
||||||
'maxlength': $localize`Description cannot be more than 1000 characters long.`
|
maxlength: $localize`Description cannot be more than 1000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ export const VIDEO_CHANNEL_SUPPORT_VALIDATOR: BuildFormValidator = {
|
||||||
Validators.maxLength(1000)
|
Validators.maxLength(1000)
|
||||||
],
|
],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'minlength': $localize`Support text must be at least 3 characters long.`,
|
minlength: $localize`Support text must be at least 3 characters long.`,
|
||||||
'maxlength': $localize`Support text cannot be more than 1000 characters long`
|
maxlength: $localize`Support text cannot be more than 1000 characters long`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { BuildFormValidator } from './form-validator.model'
|
||||||
export const VIDEO_COMMENT_TEXT_VALIDATOR: BuildFormValidator = {
|
export const VIDEO_COMMENT_TEXT_VALIDATOR: BuildFormValidator = {
|
||||||
VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ],
|
VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ],
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
'required': $localize`Comment is required.`,
|
required: $localize`Comment is required.`,
|
||||||
'minlength': $localize`Comment must be at least 2 characters long.`,
|
minlength: $localize`Comment must be at least 2 characters long.`,
|
||||||
'maxlength': $localize`Comment cannot be more than 3000 characters long.`
|
maxlength: $localize`Comment cannot be more than 3000 characters long.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user