Lazy load static objects
This commit is contained in:
parent
5dfb7c1dec
commit
ba430d7516
|
@ -5,7 +5,8 @@ import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-a
|
||||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||||
import { MarkdownService } from '@app/shared/renderer'
|
import { MarkdownService } from '@app/shared/renderer'
|
||||||
import { forkJoin } from 'rxjs'
|
import { forkJoin } from 'rxjs'
|
||||||
import { first } from 'rxjs/operators'
|
import { map, switchMap } from 'rxjs/operators'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-about-instance',
|
selector: 'my-about-instance',
|
||||||
|
@ -33,6 +34,8 @@ export class AboutInstanceComponent implements OnInit {
|
||||||
languages: string[] = []
|
languages: string[] = []
|
||||||
categories: string[] = []
|
categories: string[] = []
|
||||||
|
|
||||||
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
|
@ -42,25 +45,35 @@ export class AboutInstanceComponent implements OnInit {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get instanceName () {
|
get instanceName () {
|
||||||
return this.serverService.getConfig().instance.name
|
return this.serverConfig.instance.name
|
||||||
}
|
}
|
||||||
|
|
||||||
get isContactFormEnabled () {
|
get isContactFormEnabled () {
|
||||||
return this.serverService.getConfig().email.enabled && this.serverService.getConfig().contactForm.enabled
|
return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
get isNSFW () {
|
get isNSFW () {
|
||||||
return this.serverService.getConfig().instance.isNSFW
|
return this.serverConfig.instance.isNSFW
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
forkJoin([
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
this.instanceService.getAbout(),
|
this.serverService.getConfig()
|
||||||
this.serverService.localeObservable.pipe(first()),
|
.subscribe(config => this.serverConfig = config)
|
||||||
this.serverService.videoLanguagesLoaded.pipe(first()),
|
|
||||||
this.serverService.videoCategoriesLoaded.pipe(first())
|
this.instanceService.getAbout()
|
||||||
]).subscribe(
|
.pipe(
|
||||||
async ([ about, translations ]) => {
|
switchMap(about => {
|
||||||
|
return forkJoin([
|
||||||
|
this.instanceService.buildTranslatedLanguages(about),
|
||||||
|
this.instanceService.buildTranslatedCategories(about)
|
||||||
|
]).pipe(map(([ languages, categories ]) => ({ about, languages, categories })))
|
||||||
|
})
|
||||||
|
).subscribe(
|
||||||
|
async ({ about, languages, categories }) => {
|
||||||
|
this.languages = languages
|
||||||
|
this.categories = categories
|
||||||
|
|
||||||
this.shortDescription = about.instance.shortDescription
|
this.shortDescription = about.instance.shortDescription
|
||||||
|
|
||||||
this.creationReason = about.instance.creationReason
|
this.creationReason = about.instance.creationReason
|
||||||
|
@ -68,9 +81,6 @@ export class AboutInstanceComponent implements OnInit {
|
||||||
this.businessModel = about.instance.businessModel
|
this.businessModel = about.instance.businessModel
|
||||||
|
|
||||||
this.html = await this.instanceService.buildHtml(about)
|
this.html = await this.instanceService.buildHtml(about)
|
||||||
|
|
||||||
this.languages = this.instanceService.buildTranslatedLanguages(about, translations)
|
|
||||||
this.categories = this.instanceService.buildTranslatedCategories(about, translations)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
() => this.notifier.error(this.i18n('Cannot get about information from server'))
|
() => this.notifier.error(this.i18n('Cannot get about information from server'))
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||||
import { FormReactive, InstanceValidatorsService } from '@app/shared'
|
import { FormReactive, InstanceValidatorsService } from '@app/shared'
|
||||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-contact-admin-modal',
|
selector: 'my-contact-admin-modal',
|
||||||
|
@ -18,6 +19,7 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
|
||||||
error: string
|
error: string
|
||||||
|
|
||||||
private openedModal: NgbModalRef
|
private openedModal: NgbModalRef
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
|
@ -32,10 +34,14 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get instanceName () {
|
get instanceName () {
|
||||||
return this.serverService.getConfig().instance.name
|
return this.serverConfig.instance.name
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
fromName: this.instanceValidatorsService.FROM_NAME,
|
fromName: this.instanceValidatorsService.FROM_NAME,
|
||||||
fromEmail: this.instanceValidatorsService.FROM_EMAIL,
|
fromEmail: this.instanceValidatorsService.FROM_EMAIL,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
import { SelectItem } from 'primeng/api'
|
import { SelectItem } from 'primeng/api'
|
||||||
import { forkJoin } from 'rxjs'
|
import { forkJoin } from 'rxjs'
|
||||||
import { first } from 'rxjs/operators'
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-edit-custom-config',
|
selector: 'my-edit-custom-config',
|
||||||
|
@ -24,6 +24,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
languageItems: SelectItem[] = []
|
languageItems: SelectItem[] = []
|
||||||
categoryItems: SelectItem[] = []
|
categoryItems: SelectItem[] = []
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
private customConfigValidatorsService: CustomConfigValidatorsService,
|
private customConfigValidatorsService: CustomConfigValidatorsService,
|
||||||
|
@ -84,7 +86,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get availableThemes () {
|
get availableThemes () {
|
||||||
return this.serverService.getConfig().theme.registered
|
return this.serverConfig.theme.registered
|
||||||
.map(t => t.name)
|
.map(t => t.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +95,10 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
const formGroupData: { [key in keyof CustomConfig ]: any } = {
|
const formGroupData: { [key in keyof CustomConfig ]: any } = {
|
||||||
instance: {
|
instance: {
|
||||||
name: this.customConfigValidatorsService.INSTANCE_NAME,
|
name: this.customConfigValidatorsService.INSTANCE_NAME,
|
||||||
|
@ -218,16 +224,13 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
forkJoin([
|
forkJoin([
|
||||||
this.configService.getCustomConfig(),
|
this.configService.getCustomConfig(),
|
||||||
this.serverService.videoLanguagesLoaded.pipe(first()), // First so the observable completes
|
this.serverService.getVideoLanguages(),
|
||||||
this.serverService.videoCategoriesLoaded.pipe(first())
|
this.serverService.getVideoCategories()
|
||||||
]).subscribe(
|
]).subscribe(
|
||||||
([ config ]) => {
|
([ config, languages, categories ]) => {
|
||||||
this.customConfig = config
|
this.customConfig = config
|
||||||
|
|
||||||
const languages = this.serverService.getVideoLanguages()
|
|
||||||
this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
|
this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
|
||||||
|
|
||||||
const categories = this.serverService.getVideoCategories()
|
|
||||||
this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
|
this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
|
||||||
|
|
||||||
this.updateForm()
|
this.updateForm()
|
||||||
|
@ -249,12 +252,14 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
async formValidated () {
|
async formValidated () {
|
||||||
this.configService.updateCustomConfig(this.form.value)
|
this.configService.updateCustomConfig(this.form.value)
|
||||||
|
.pipe(
|
||||||
|
)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.customConfig = res
|
this.customConfig = res
|
||||||
|
|
||||||
// Reload general configuration
|
// Reload general configuration
|
||||||
this.serverService.loadConfig()
|
this.serverService.resetConfig()
|
||||||
|
|
||||||
this.updateForm()
|
this.updateForm()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { UserRight } from '../../../../../shared'
|
import { UserRight } from '../../../../../shared'
|
||||||
import { AuthService, ServerService } from '@app/core'
|
import { AuthService, ServerService } from '@app/core'
|
||||||
|
|
||||||
|
@ -6,14 +6,18 @@ import { AuthService, ServerService } from '@app/core'
|
||||||
templateUrl: './moderation.component.html',
|
templateUrl: './moderation.component.html',
|
||||||
styleUrls: [ './moderation.component.scss' ]
|
styleUrls: [ './moderation.component.scss' ]
|
||||||
})
|
})
|
||||||
export class ModerationComponent {
|
export class ModerationComponent implements OnInit {
|
||||||
autoBlacklistVideosEnabled: boolean
|
autoBlacklistVideosEnabled = false
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private serverService: ServerService
|
private serverService: ServerService
|
||||||
) {
|
) { }
|
||||||
this.autoBlacklistVideosEnabled = this.serverService.getConfig().autoBlacklist.videos.ofUsers.enabled
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.autoBlacklistVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasVideoAbusesRight () {
|
hasVideoAbusesRight () {
|
||||||
|
|
|
@ -33,11 +33,18 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
|
||||||
private i18n: I18n
|
private i18n: I18n
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
// don't filter if auto-blacklist not enabled as this will be only list
|
ngOnInit () {
|
||||||
if (this.serverService.getConfig().autoBlacklist.videos.ofUsers.enabled) {
|
this.serverService.getConfig()
|
||||||
this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
|
.subscribe(config => {
|
||||||
}
|
// don't filter if auto-blacklist not enabled as this will be only list
|
||||||
|
if (config.autoBlacklist.videos.ofUsers.enabled) {
|
||||||
|
this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.initialize()
|
||||||
|
|
||||||
this.videoBlacklistActions = [
|
this.videoBlacklistActions = [
|
||||||
{
|
{
|
||||||
|
@ -47,10 +54,6 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
|
||||||
this.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
getVideoUrl (videoBlacklist: VideoBlacklist) {
|
getVideoUrl (videoBlacklist: VideoBlacklist) {
|
||||||
return Video.buildClientUrl(videoBlacklist.video.uuid)
|
return Video.buildClientUrl(videoBlacklist.video.uuid)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ export class UserCreateComponent extends UserEdit implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
super.ngOnInit()
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
role: UserRole.USER.toString(),
|
role: UserRole.USER.toString(),
|
||||||
videoQuota: '-1',
|
videoQuota: '-1',
|
||||||
|
|
|
@ -1,21 +1,30 @@
|
||||||
import { AuthService, ServerService } from '../../../core'
|
import { AuthService, ServerService } from '../../../core'
|
||||||
import { FormReactive } from '../../../shared'
|
import { FormReactive } from '../../../shared'
|
||||||
import { USER_ROLE_LABELS, UserRole, VideoResolution } from '../../../../../../shared'
|
import { ServerConfig, USER_ROLE_LABELS, UserRole, VideoResolution } from '../../../../../../shared'
|
||||||
import { ConfigService } from '@app/+admin/config/shared/config.service'
|
import { ConfigService } from '@app/+admin/config/shared/config.service'
|
||||||
import { UserAdminFlag } from '@shared/models/users/user-flag.model'
|
import { UserAdminFlag } from '@shared/models/users/user-flag.model'
|
||||||
|
import { OnInit } from '@angular/core'
|
||||||
|
|
||||||
export abstract class UserEdit extends FormReactive {
|
export abstract class UserEdit extends FormReactive implements OnInit {
|
||||||
videoQuotaOptions: { value: string, label: string }[] = []
|
videoQuotaOptions: { value: string, label: string }[] = []
|
||||||
videoQuotaDailyOptions: { value: string, label: string }[] = []
|
videoQuotaDailyOptions: { value: string, label: string }[] = []
|
||||||
username: string
|
username: string
|
||||||
userId: number
|
userId: number
|
||||||
|
|
||||||
|
protected serverConfig: ServerConfig
|
||||||
|
|
||||||
protected abstract serverService: ServerService
|
protected abstract serverService: ServerService
|
||||||
protected abstract configService: ConfigService
|
protected abstract configService: ConfigService
|
||||||
protected abstract auth: AuthService
|
protected abstract auth: AuthService
|
||||||
abstract isCreation (): boolean
|
abstract isCreation (): boolean
|
||||||
abstract getFormButtonTitle (): string
|
abstract getFormButtonTitle (): string
|
||||||
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
}
|
||||||
|
|
||||||
getRoles () {
|
getRoles () {
|
||||||
const authUser = this.auth.getUser()
|
const authUser = this.auth.getUser()
|
||||||
|
|
||||||
|
@ -32,12 +41,12 @@ export abstract class UserEdit extends FormReactive {
|
||||||
isTranscodingInformationDisplayed () {
|
isTranscodingInformationDisplayed () {
|
||||||
const formVideoQuota = parseInt(this.form.value['videoQuota'], 10)
|
const formVideoQuota = parseInt(this.form.value['videoQuota'], 10)
|
||||||
|
|
||||||
return this.serverService.getConfig().transcoding.enabledResolutions.length !== 0 &&
|
return this.serverConfig.transcoding.enabledResolutions.length !== 0 &&
|
||||||
formVideoQuota > 0
|
formVideoQuota > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
computeQuotaWithTranscoding () {
|
computeQuotaWithTranscoding () {
|
||||||
const transcodingConfig = this.serverService.getConfig().transcoding
|
const transcodingConfig = this.serverConfig.transcoding
|
||||||
|
|
||||||
const resolutions = transcodingConfig.enabledResolutions
|
const resolutions = transcodingConfig.enabledResolutions
|
||||||
const higherResolution = VideoResolution.H_4K
|
const higherResolution = VideoResolution.H_4K
|
||||||
|
|
|
@ -43,6 +43,8 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
super.ngOnInit()
|
||||||
|
|
||||||
const defaultValues = { videoQuota: '-1', videoQuotaDaily: '-1' }
|
const defaultValues = { videoQuota: '-1', videoQuotaDaily: '-1' }
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
email: this.userValidatorsService.USER_EMAIL,
|
email: this.userValidatorsService.USER_EMAIL,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { SortMeta } from 'primeng/components/common/sortmeta'
|
||||||
import { ConfirmService, ServerService } from '../../../core'
|
import { ConfirmService, ServerService } from '../../../core'
|
||||||
import { RestPagination, RestTable, UserService } from '../../../shared'
|
import { RestPagination, RestTable, UserService } from '../../../shared'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { User } from '../../../../../../shared'
|
import { ServerConfig, User } from '../../../../../../shared'
|
||||||
import { UserBanModalComponent } from '@app/shared/moderation'
|
import { UserBanModalComponent } from '@app/shared/moderation'
|
||||||
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
selectedUsers: User[] = []
|
selectedUsers: User[] = []
|
||||||
bulkUserActions: DropdownAction<User[]>[] = []
|
bulkUserActions: DropdownAction<User[]>[] = []
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
private confirmService: ConfirmService,
|
private confirmService: ConfirmService,
|
||||||
|
@ -41,10 +43,14 @@ export class UserListComponent extends RestTable implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get requiresEmailVerification () {
|
get requiresEmailVerification () {
|
||||||
return this.serverService.getConfig().signup.requiresEmailVerification
|
return this.serverConfig.signup.requiresEmailVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.initialize()
|
this.initialize()
|
||||||
|
|
||||||
this.bulkUserActions = [
|
this.bulkUserActions = [
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val
|
||||||
import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
|
import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
|
||||||
import { User } from '../../../../../../shared'
|
import { User } from '../../../../../../shared'
|
||||||
import { tap } from 'rxjs/operators'
|
import { tap } from 'rxjs/operators'
|
||||||
|
import { forkJoin } from 'rxjs'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-account-change-email',
|
selector: 'my-account-change-email',
|
||||||
|
@ -45,29 +46,29 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni
|
||||||
const password = this.form.value[ 'password' ]
|
const password = this.form.value[ 'password' ]
|
||||||
const email = this.form.value[ 'new-email' ]
|
const email = this.form.value[ 'new-email' ]
|
||||||
|
|
||||||
this.userService.changeEmail(password, email)
|
forkJoin([
|
||||||
.pipe(
|
this.serverService.getConfig(),
|
||||||
tap(() => this.authService.refreshUserInformation())
|
this.userService.changeEmail(password, email)
|
||||||
)
|
]).pipe(tap(() => this.authService.refreshUserInformation()))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => {
|
([ config ]) => {
|
||||||
this.form.reset()
|
this.form.reset()
|
||||||
|
|
||||||
if (this.serverService.getConfig().signup.requiresEmailVerification) {
|
if (config.signup.requiresEmailVerification) {
|
||||||
this.success = this.i18n('Please check your emails to verify your new email.')
|
this.success = this.i18n('Please check your emails to verify your new email.')
|
||||||
} else {
|
} else {
|
||||||
this.success = this.i18n('Email updated.')
|
this.success = this.i18n('Email updated.')
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
err => {
|
|
||||||
if (err.status === 401) {
|
|
||||||
this.error = this.i18n('You current password is invalid.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.error = err.message
|
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
|
|
||||||
|
err => {
|
||||||
|
if (err.status === 401) {
|
||||||
|
this.error = this.i18n('You current password is invalid.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.error = err.message
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, Input, OnInit } from '@angular/core'
|
||||||
import { Notifier, ServerService } from '@app/core'
|
import { Notifier, ServerService } from '@app/core'
|
||||||
import { UserUpdateMe } from '../../../../../../shared'
|
import { ServerConfig, UserUpdateMe } from '../../../../../../shared'
|
||||||
import { AuthService } from '../../../core'
|
import { AuthService } from '../../../core'
|
||||||
import { FormReactive, User, UserService } from '../../../shared'
|
import { FormReactive, User, UserService } from '../../../shared'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
@ -16,6 +16,8 @@ export class MyAccountInterfaceSettingsComponent extends FormReactive implements
|
||||||
@Input() user: User = null
|
@Input() user: User = null
|
||||||
@Input() userInformationLoaded: Subject<any>
|
@Input() userInformationLoaded: Subject<any>
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
@ -28,11 +30,15 @@ export class MyAccountInterfaceSettingsComponent extends FormReactive implements
|
||||||
}
|
}
|
||||||
|
|
||||||
get availableThemes () {
|
get availableThemes () {
|
||||||
return this.serverService.getConfig().theme.registered
|
return this.serverConfig.theme.registered
|
||||||
.map(t => t.name)
|
.map(t => t.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
theme: null
|
theme: null
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
|
||||||
webNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any
|
webNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any
|
||||||
labelNotifications: { [ id in keyof UserNotificationSetting ]: string } = {} as any
|
labelNotifications: { [ id in keyof UserNotificationSetting ]: string } = {} as any
|
||||||
rightNotifications: { [ id in keyof Partial<UserNotificationSetting> ]: UserRight } = {} as any
|
rightNotifications: { [ id in keyof Partial<UserNotificationSetting> ]: UserRight } = {} as any
|
||||||
emailEnabled: boolean
|
emailEnabled = false
|
||||||
|
|
||||||
private savePreferences = debounce(this.savePreferencesImpl.bind(this), 500)
|
private savePreferences = debounce(this.savePreferencesImpl.bind(this), 500)
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private notifier: Notifier
|
private notifier: Notifier
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.labelNotifications = {
|
this.labelNotifications = {
|
||||||
newVideoFromSubscription: this.i18n('New video from your subscriptions'),
|
newVideoFromSubscription: this.i18n('New video from your subscriptions'),
|
||||||
newCommentOnMyVideo: this.i18n('New comment on your video'),
|
newCommentOnMyVideo: this.i18n('New comment on your video'),
|
||||||
|
@ -55,11 +54,14 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
|
||||||
newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW,
|
newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW,
|
||||||
autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION
|
autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emailEnabled = this.serverService.getConfig().email.enabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => {
|
||||||
|
this.emailEnabled = config.email.enabled
|
||||||
|
})
|
||||||
|
|
||||||
this.userInformationLoaded.subscribe(() => this.loadNotificationSettings())
|
this.userInformationLoaded.subscribe(() => this.loadNotificationSettings())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,9 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
|
||||||
})
|
})
|
||||||
|
|
||||||
forkJoin([
|
forkJoin([
|
||||||
this.serverService.videoLanguagesLoaded.pipe(first()),
|
this.serverService.getVideoLanguages(),
|
||||||
this.userInformationLoaded.pipe(first())
|
this.userInformationLoaded.pipe(first())
|
||||||
]).subscribe(() => {
|
]).subscribe(([ languages ]) => {
|
||||||
const languages = this.serverService.getVideoLanguages()
|
|
||||||
|
|
||||||
this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ]
|
this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ]
|
||||||
this.languageItems = this.languageItems
|
this.languageItems = this.languageItems
|
||||||
.concat(languages.map(l => ({ label: l.label, value: l.id })))
|
.concat(languages.map(l => ({ label: l.label, value: l.id })))
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
|
import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-account-video-channel-update',
|
selector: 'my-account-video-channel-update',
|
||||||
|
@ -21,6 +22,7 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
|
||||||
|
|
||||||
private paramsSub: Subscription
|
private paramsSub: Subscription
|
||||||
private oldSupportField: string
|
private oldSupportField: string
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
|
@ -37,6 +39,10 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME,
|
'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME,
|
||||||
description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION,
|
description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION,
|
||||||
|
@ -109,11 +115,11 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxAvatarSize () {
|
get maxAvatarSize () {
|
||||||
return this.serverService.getConfig().avatar.file.size.max
|
return this.serverConfig.avatar.file.size.max
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarExtensions () {
|
get avatarExtensions () {
|
||||||
return this.serverService.getConfig().avatar.file.extensions.join(',')
|
return this.serverConfig.avatar.file.extensions.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
isCreation () {
|
isCreation () {
|
||||||
|
|
|
@ -47,15 +47,14 @@ export class MyAccountVideoPlaylistCreateComponent extends MyAccountVideoPlaylis
|
||||||
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
||||||
.catch(err => console.error('Cannot populate user video channels.', err))
|
.catch(err => console.error('Cannot populate user video channels.', err))
|
||||||
|
|
||||||
this.serverService.videoPlaylistPrivaciesLoaded.subscribe(
|
this.serverService.getVideoPlaylistPrivacies()
|
||||||
() => {
|
.subscribe(videoPlaylistPrivacies => {
|
||||||
this.videoPlaylistPrivacies = this.serverService.getVideoPlaylistPrivacies()
|
this.videoPlaylistPrivacies = videoPlaylistPrivacies
|
||||||
|
|
||||||
this.form.patchValue({
|
this.form.patchValue({
|
||||||
privacy: VideoPlaylistPrivacy.PRIVATE
|
privacy: VideoPlaylistPrivacy.PRIVATE
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
formValidated () {
|
formValidated () {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { AuthService, Notifier, ServerService } from '@app/core'
|
import { AuthService, Notifier, ServerService } from '@app/core'
|
||||||
import { Subscription } from 'rxjs'
|
import { forkJoin, Subscription } from 'rxjs'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
import { MyAccountVideoPlaylistEdit } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-edit'
|
import { MyAccountVideoPlaylistEdit } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-edit'
|
||||||
|
@ -56,13 +56,17 @@ export class MyAccountVideoPlaylistUpdateComponent extends MyAccountVideoPlaylis
|
||||||
this.paramsSub = this.route.params
|
this.paramsSub = this.route.params
|
||||||
.pipe(
|
.pipe(
|
||||||
map(routeParams => routeParams['videoPlaylistId']),
|
map(routeParams => routeParams['videoPlaylistId']),
|
||||||
switchMap(videoPlaylistId => this.videoPlaylistService.getVideoPlaylist(videoPlaylistId)),
|
switchMap(videoPlaylistId => {
|
||||||
delayWhen(() => this.serverService.videoPlaylistPrivaciesLoaded)
|
return forkJoin([
|
||||||
|
this.videoPlaylistService.getVideoPlaylist(videoPlaylistId),
|
||||||
|
this.serverService.getVideoPlaylistPrivacies()
|
||||||
|
])
|
||||||
|
})
|
||||||
)
|
)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
videoPlaylistToUpdate => {
|
([ videoPlaylistToUpdate, videoPlaylistPrivacies]) => {
|
||||||
this.videoPlaylistPrivacies = this.serverService.getVideoPlaylistPrivacies()
|
|
||||||
this.videoPlaylistToUpdate = videoPlaylistToUpdate
|
this.videoPlaylistToUpdate = videoPlaylistToUpdate
|
||||||
|
this.videoPlaylistPrivacies = videoPlaylistPrivacies
|
||||||
|
|
||||||
this.hydrateFormFromPlaylist()
|
this.hydrateFormFromPlaylist()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,20 +1,28 @@
|
||||||
import { Component } from '@angular/core'
|
import { Component, OnInit } from '@angular/core'
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component'
|
import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-my-account',
|
selector: 'my-my-account',
|
||||||
templateUrl: './my-account.component.html',
|
templateUrl: './my-account.component.html',
|
||||||
styleUrls: [ './my-account.component.scss' ]
|
styleUrls: [ './my-account.component.scss' ]
|
||||||
})
|
})
|
||||||
export class MyAccountComponent {
|
export class MyAccountComponent implements OnInit {
|
||||||
menuEntries: TopMenuDropdownParam[] = []
|
menuEntries: TopMenuDropdownParam[] = []
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private i18n: I18n
|
private i18n: I18n
|
||||||
) {
|
) { }
|
||||||
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
const libraryEntries: TopMenuDropdownParam = {
|
const libraryEntries: TopMenuDropdownParam = {
|
||||||
label: this.i18n('My library'),
|
label: this.i18n('My library'),
|
||||||
|
@ -91,7 +99,7 @@ export class MyAccountComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoImportEnabled () {
|
isVideoImportEnabled () {
|
||||||
const importConfig = this.serverService.getConfig().import.videos
|
const importConfig = this.serverConfig.import.videos
|
||||||
|
|
||||||
return importConfig.http.enabled || importConfig.torrent.enabled
|
return importConfig.http.enabled || importConfig.torrent.enabled
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,35 @@
|
||||||
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'
|
import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
|
||||||
import { ServerService } from '../../core/server'
|
import { ServerService } from '../../core/server'
|
||||||
import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
|
import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
|
||||||
import { Account } from '@app/shared/account/account.model'
|
import { Account } from '@app/shared/account/account.model'
|
||||||
import { Notifier } from '@app/core'
|
import { Notifier } from '@app/core'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-actor-avatar-info',
|
selector: 'my-actor-avatar-info',
|
||||||
templateUrl: './actor-avatar-info.component.html',
|
templateUrl: './actor-avatar-info.component.html',
|
||||||
styleUrls: [ './actor-avatar-info.component.scss' ]
|
styleUrls: [ './actor-avatar-info.component.scss' ]
|
||||||
})
|
})
|
||||||
export class ActorAvatarInfoComponent {
|
export class ActorAvatarInfoComponent implements OnInit {
|
||||||
@ViewChild('avatarfileInput', { static: false }) avatarfileInput: ElementRef<HTMLInputElement>
|
@ViewChild('avatarfileInput', { static: false }) avatarfileInput: ElementRef<HTMLInputElement>
|
||||||
|
|
||||||
@Input() actor: VideoChannel | Account
|
@Input() actor: VideoChannel | Account
|
||||||
|
|
||||||
@Output() avatarChange = new EventEmitter<FormData>()
|
@Output() avatarChange = new EventEmitter<FormData>()
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private notifier: Notifier
|
private notifier: Notifier
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
}
|
||||||
|
|
||||||
onAvatarChange () {
|
onAvatarChange () {
|
||||||
const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
|
const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
|
||||||
if (avatarfile.size > this.maxAvatarSize) {
|
if (avatarfile.size > this.maxAvatarSize) {
|
||||||
|
@ -35,10 +44,10 @@ export class ActorAvatarInfoComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxAvatarSize () {
|
get maxAvatarSize () {
|
||||||
return this.serverService.getConfig().avatar.file.size.max
|
return this.serverConfig.avatar.file.size.max
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarExtensions () {
|
get avatarExtensions () {
|
||||||
return this.serverService.getConfig().avatar.file.extensions.join(',')
|
return this.serverConfig.avatar.file.extensions.join(',')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ const registerRoutes: Routes = [
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
serverConfigLoaded: ServerConfigResolver
|
serverConfig: ServerConfigResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,10 +4,11 @@ import { UserService, UserValidatorsService } from '@app/shared'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { UserRegister } from '@shared/models/users/user-register.model'
|
import { UserRegister } from '@shared/models/users/user-register.model'
|
||||||
import { FormGroup } from '@angular/forms'
|
import { FormGroup } from '@angular/forms'
|
||||||
import { About } from '@shared/models/server'
|
import { About, ServerConfig } from '@shared/models/server'
|
||||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||||
import { HooksService } from '@app/core/plugins/hooks.service'
|
import { HooksService } from '@app/core/plugins/hooks.service'
|
||||||
import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
import { ActivatedRoute } from '@angular/router'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-register',
|
selector: 'my-register',
|
||||||
|
@ -34,7 +35,10 @@ export class RegisterComponent implements OnInit {
|
||||||
formStepUser: FormGroup
|
formStepUser: FormGroup
|
||||||
formStepChannel: FormGroup
|
formStepChannel: FormGroup
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
private route: ActivatedRoute,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private userValidatorsService: UserValidatorsService,
|
private userValidatorsService: UserValidatorsService,
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
|
@ -48,10 +52,12 @@ export class RegisterComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get requiresEmailVerification () {
|
get requiresEmailVerification () {
|
||||||
return this.serverService.getConfig().signup.requiresEmailVerification
|
return this.serverConfig.signup.requiresEmailVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.route.snapshot.data.serverConfig
|
||||||
|
|
||||||
this.instanceService.getAbout()
|
this.instanceService.getAbout()
|
||||||
.subscribe(
|
.subscribe(
|
||||||
async about => {
|
async about => {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { ServerService } from '@app/core/server'
|
||||||
import { FormReactive, UserService } from '@app/shared'
|
import { FormReactive, UserService } from '@app/shared'
|
||||||
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
|
import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-verify-account-ask-send-email',
|
selector: 'my-verify-account-ask-send-email',
|
||||||
|
@ -13,6 +14,7 @@ import { UserValidatorsService } from '@app/shared/forms/form-validators/user-va
|
||||||
})
|
})
|
||||||
|
|
||||||
export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit {
|
export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit {
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
|
@ -27,10 +29,14 @@ export class VerifyAccountAskSendEmailComponent extends FormReactive implements
|
||||||
}
|
}
|
||||||
|
|
||||||
get requiresEmailVerification () {
|
get requiresEmailVerification () {
|
||||||
return this.serverService.getConfig().signup.requiresEmailVerification
|
return this.serverConfig.signup.requiresEmailVerification
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
'verify-email-email': this.userValidatorsService.USER_EMAIL
|
'verify-email-email': this.userValidatorsService.USER_EMAIL
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants'
|
import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants'
|
||||||
import { WelcomeModalComponent } from '@app/modal/welcome-modal.component'
|
import { WelcomeModalComponent } from '@app/modal/welcome-modal.component'
|
||||||
import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component'
|
import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component'
|
||||||
import { UserRole } from '@shared/models'
|
import { ServerConfig, UserRole } from '@shared/models'
|
||||||
import { User } from '@app/shared'
|
import { User } from '@app/shared'
|
||||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ export class AppComponent implements OnInit {
|
||||||
|
|
||||||
customCSS: SafeHtml
|
customCSS: SafeHtml
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private i18n: I18n,
|
private i18n: I18n,
|
||||||
private viewportScroller: ViewportScroller,
|
private viewportScroller: ViewportScroller,
|
||||||
|
@ -52,7 +54,7 @@ export class AppComponent implements OnInit {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
get instanceName () {
|
get instanceName () {
|
||||||
return this.serverService.getConfig().instance.name
|
return this.serverConfig.instance.name
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultRoute () {
|
get defaultRoute () {
|
||||||
|
@ -62,6 +64,10 @@ export class AppComponent implements OnInit {
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
document.getElementById('incompatible-browser').className += ' browser-ok'
|
document.getElementById('incompatible-browser').className += ' browser-ok'
|
||||||
|
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.loadPlugins()
|
this.loadPlugins()
|
||||||
this.themeService.initialize()
|
this.themeService.initialize()
|
||||||
|
|
||||||
|
@ -72,14 +78,6 @@ export class AppComponent implements OnInit {
|
||||||
this.authService.refreshUserInformation()
|
this.authService.refreshUserInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load custom data from server
|
|
||||||
this.serverService.loadConfig()
|
|
||||||
this.serverService.loadVideoCategories()
|
|
||||||
this.serverService.loadVideoLanguages()
|
|
||||||
this.serverService.loadVideoLicences()
|
|
||||||
this.serverService.loadVideoPrivacies()
|
|
||||||
this.serverService.loadVideoPlaylistPrivacies()
|
|
||||||
|
|
||||||
// Do not display menu on small screens
|
// Do not display menu on small screens
|
||||||
if (this.screenService.isInSmallView()) {
|
if (this.screenService.isInSmallView()) {
|
||||||
this.isMenuDisplayed = false
|
this.isMenuDisplayed = false
|
||||||
|
@ -187,10 +185,8 @@ export class AppComponent implements OnInit {
|
||||||
|
|
||||||
private injectJS () {
|
private injectJS () {
|
||||||
// Inject JS
|
// Inject JS
|
||||||
this.serverService.configLoaded
|
this.serverService.getConfig()
|
||||||
.subscribe(() => {
|
.subscribe(config => {
|
||||||
const config = this.serverService.getConfig()
|
|
||||||
|
|
||||||
if (config.instance.customizations.javascript) {
|
if (config.instance.customizations.javascript) {
|
||||||
try {
|
try {
|
||||||
// tslint:disable:no-eval
|
// tslint:disable:no-eval
|
||||||
|
@ -204,17 +200,14 @@ export class AppComponent implements OnInit {
|
||||||
|
|
||||||
private injectCSS () {
|
private injectCSS () {
|
||||||
// Inject CSS if modified (admin config settings)
|
// Inject CSS if modified (admin config settings)
|
||||||
this.serverService.configLoaded
|
this.serverService.configReloaded
|
||||||
.pipe(skip(1)) // We only want to subscribe to reloads, because the CSS is already injected by the server
|
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
const headStyle = document.querySelector('style.custom-css-style')
|
const headStyle = document.querySelector('style.custom-css-style')
|
||||||
if (headStyle) headStyle.parentNode.removeChild(headStyle)
|
if (headStyle) headStyle.parentNode.removeChild(headStyle)
|
||||||
|
|
||||||
const config = this.serverService.getConfig()
|
|
||||||
|
|
||||||
// We test customCSS if the admin removed the css
|
// We test customCSS if the admin removed the css
|
||||||
if (this.customCSS || config.instance.customizations.css) {
|
if (this.customCSS || this.serverConfig.instance.customizations.css) {
|
||||||
const styleTag = '<style>' + config.instance.customizations.css + '</style>'
|
const styleTag = '<style>' + this.serverConfig.instance.customizations.css + '</style>'
|
||||||
this.customCSS = this.domSanitizer.bypassSecurityTrustHtml(styleTag)
|
this.customCSS = this.domSanitizer.bypassSecurityTrustHtml(styleTag)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -227,25 +220,22 @@ export class AppComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async openModalsIfNeeded () {
|
private async openModalsIfNeeded () {
|
||||||
this.serverService.configLoaded
|
this.authService.userInformationLoaded
|
||||||
.pipe(
|
.pipe(
|
||||||
first(),
|
|
||||||
switchMap(() => this.authService.userInformationLoaded),
|
|
||||||
map(() => this.authService.getUser()),
|
map(() => this.authService.getUser()),
|
||||||
filter(user => user.role === UserRole.ADMINISTRATOR)
|
filter(user => user.role === UserRole.ADMINISTRATOR)
|
||||||
).subscribe(user => setTimeout(() => this.openAdminModals(user))) // setTimeout because of ngIf in template
|
).subscribe(user => setTimeout(() => this._openAdminModalsIfNeeded(user))) // setTimeout because of ngIf in template
|
||||||
}
|
}
|
||||||
|
|
||||||
private async openAdminModals (user: User) {
|
private async _openAdminModalsIfNeeded (user: User) {
|
||||||
if (user.noWelcomeModal !== true) return this.welcomeModal.show()
|
if (user.noWelcomeModal !== true) return this.welcomeModal.show()
|
||||||
|
|
||||||
const config = this.serverService.getConfig()
|
if (user.noInstanceConfigWarningModal === true || !this.serverConfig.signup.allowed) return
|
||||||
if (user.noInstanceConfigWarningModal === true || !config.signup.allowed) return
|
|
||||||
|
|
||||||
this.instanceService.getAbout()
|
this.instanceService.getAbout()
|
||||||
.subscribe(about => {
|
.subscribe(about => {
|
||||||
if (
|
if (
|
||||||
config.instance.name.toLowerCase() === 'peertube' ||
|
this.serverConfig.instance.name.toLowerCase() === 'peertube' ||
|
||||||
!about.instance.terms ||
|
!about.instance.terms ||
|
||||||
!about.instance.administrator ||
|
!about.instance.administrator ||
|
||||||
!about.instance.maintenanceLifetime
|
!about.instance.maintenanceLifetime
|
||||||
|
|
|
@ -25,10 +25,10 @@ export function metaFactory (serverService: ServerService): MetaLoader {
|
||||||
return new MetaStaticLoader({
|
return new MetaStaticLoader({
|
||||||
pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
|
pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
|
||||||
pageTitleSeparator: ' - ',
|
pageTitleSeparator: ' - ',
|
||||||
get applicationName () { return serverService.getConfig().instance.name },
|
get applicationName () { return serverService.getTmpConfig().instance.name },
|
||||||
defaults: {
|
defaults: {
|
||||||
get title () { return serverService.getConfig().instance.name },
|
get title () { return serverService.getTmpConfig().instance.name },
|
||||||
get description () { return serverService.getConfig().instance.shortDescription }
|
get description () { return serverService.getTmpConfig().instance.shortDescription }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,9 +70,9 @@ export class PluginService implements ClientHook {
|
||||||
}
|
}
|
||||||
|
|
||||||
initializePlugins () {
|
initializePlugins () {
|
||||||
this.server.configLoaded
|
this.server.getConfig()
|
||||||
.subscribe(() => {
|
.subscribe(config => {
|
||||||
this.plugins = this.server.getConfig().plugin.registered
|
this.plugins = config.plugin.registered
|
||||||
|
|
||||||
this.buildScopeStruct()
|
this.buildScopeStruct()
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@ export class RedirectService {
|
||||||
private serverService: ServerService
|
private serverService: ServerService
|
||||||
) {
|
) {
|
||||||
// The config is first loaded from the cache so try to get the default route
|
// The config is first loaded from the cache so try to get the default route
|
||||||
const config = this.serverService.getConfig()
|
const tmpConfig = this.serverService.getTmpConfig()
|
||||||
if (config && config.instance && config.instance.defaultClientRoute) {
|
if (tmpConfig && tmpConfig.instance && tmpConfig.instance.defaultClientRoute) {
|
||||||
RedirectService.DEFAULT_ROUTE = config.instance.defaultClientRoute
|
RedirectService.DEFAULT_ROUTE = tmpConfig.instance.defaultClientRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load default route
|
// Load default route
|
||||||
this.serverService.configLoaded
|
this.serverService.getConfig()
|
||||||
.subscribe(() => {
|
.subscribe(config => {
|
||||||
const defaultRouteConfig = this.serverService.getConfig().instance.defaultClientRoute
|
const defaultRouteConfig = config.instance.defaultClientRoute
|
||||||
|
|
||||||
if (defaultRouteConfig) {
|
if (defaultRouteConfig) {
|
||||||
RedirectService.DEFAULT_ROUTE = defaultRouteConfig
|
RedirectService.DEFAULT_ROUTE = defaultRouteConfig
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Resolve } from '@angular/router'
|
import { Resolve } from '@angular/router'
|
||||||
import { ServerService } from '@app/core/server'
|
import { ServerService } from '@app/core/server'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerConfigResolver implements Resolve<boolean> {
|
export class ServerConfigResolver implements Resolve<ServerConfig> {
|
||||||
constructor (
|
constructor (private server: ServerService) {}
|
||||||
private server: ServerService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
resolve () {
|
resolve () {
|
||||||
// FIXME: directly returning this.server.configLoaded does not seem to work
|
return this.server.getConfig()
|
||||||
return new Promise<boolean>(res => {
|
|
||||||
return this.server.configLoaded.subscribe(() => res(true))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,36 @@
|
||||||
import { map, shareReplay, switchMap, tap } from 'rxjs/operators'
|
import { first, map, share, shareReplay, switchMap, tap } from 'rxjs/operators'
|
||||||
import { HttpClient } from '@angular/common/http'
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { Inject, Injectable, LOCALE_ID } from '@angular/core'
|
import { Inject, Injectable, LOCALE_ID } from '@angular/core'
|
||||||
import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
|
import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
|
||||||
import { Observable, of, ReplaySubject } from 'rxjs'
|
import { Observable, of, Subject } from 'rxjs'
|
||||||
import { getCompleteLocale, ServerConfig } from '../../../../../shared'
|
import { getCompleteLocale, ServerConfig } from '../../../../../shared'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos'
|
import { VideoConstant } from '../../../../../shared/models/videos'
|
||||||
import { isDefaultLocale, peertubeTranslate } from '../../../../../shared/models/i18n'
|
import { isDefaultLocale, peertubeTranslate } from '../../../../../shared/models/i18n'
|
||||||
import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
|
import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
|
||||||
import { sortBy } from '@app/shared/misc/utils'
|
import { sortBy } from '@app/shared/misc/utils'
|
||||||
import { VideoPlaylistPrivacy } from '@shared/models/videos/playlist/video-playlist-privacy.model'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerService {
|
export class ServerService {
|
||||||
private static BASE_SERVER_URL = environment.apiUrl + '/api/v1/server/'
|
|
||||||
private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/'
|
private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/'
|
||||||
private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/'
|
private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/'
|
||||||
private static BASE_VIDEO_PLAYLIST_URL = environment.apiUrl + '/api/v1/video-playlists/'
|
private static BASE_VIDEO_PLAYLIST_URL = environment.apiUrl + '/api/v1/video-playlists/'
|
||||||
private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/'
|
private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/'
|
||||||
private static CONFIG_LOCAL_STORAGE_KEY = 'server-config'
|
private static CONFIG_LOCAL_STORAGE_KEY = 'server-config'
|
||||||
|
|
||||||
configLoaded = new ReplaySubject<boolean>(1)
|
configReloaded = new Subject<void>()
|
||||||
videoPrivaciesLoaded = new ReplaySubject<boolean>(1)
|
|
||||||
videoPlaylistPrivaciesLoaded = new ReplaySubject<boolean>(1)
|
|
||||||
videoCategoriesLoaded = new ReplaySubject<boolean>(1)
|
|
||||||
videoLicencesLoaded = new ReplaySubject<boolean>(1)
|
|
||||||
videoLanguagesLoaded = new ReplaySubject<boolean>(1)
|
|
||||||
localeObservable: Observable<any>
|
|
||||||
|
|
||||||
|
private localeObservable: Observable<any>
|
||||||
|
private videoLicensesObservable: Observable<VideoConstant<number>[]>
|
||||||
|
private videoCategoriesObservable: Observable<VideoConstant<number>[]>
|
||||||
|
private videoPrivaciesObservable: Observable<VideoConstant<number>[]>
|
||||||
|
private videoPlaylistPrivaciesObservable: Observable<VideoConstant<number>[]>
|
||||||
|
private videoLanguagesObservable: Observable<VideoConstant<string>[]>
|
||||||
|
private configObservable: Observable<ServerConfig>
|
||||||
|
|
||||||
|
private configReset = false
|
||||||
|
|
||||||
|
private configLoaded = false
|
||||||
private config: ServerConfig = {
|
private config: ServerConfig = {
|
||||||
instance: {
|
instance: {
|
||||||
name: 'PeerTube',
|
name: 'PeerTube',
|
||||||
|
@ -121,132 +123,141 @@ export class ServerService {
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private videoCategories: Array<VideoConstant<number>> = []
|
|
||||||
private videoLicences: Array<VideoConstant<number>> = []
|
|
||||||
private videoLanguages: Array<VideoConstant<string>> = []
|
|
||||||
private videoPrivacies: Array<VideoConstant<VideoPrivacy>> = []
|
|
||||||
private videoPlaylistPrivacies: Array<VideoConstant<VideoPlaylistPrivacy>> = []
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
@Inject(LOCALE_ID) private localeId: string
|
@Inject(LOCALE_ID) private localeId: string
|
||||||
) {
|
) {
|
||||||
this.loadServerLocale()
|
|
||||||
this.loadConfigLocally()
|
this.loadConfigLocally()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadConfig () {
|
|
||||||
this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL)
|
|
||||||
.pipe(tap(this.saveConfigLocally))
|
|
||||||
.subscribe(data => {
|
|
||||||
this.config = data
|
|
||||||
|
|
||||||
this.configLoaded.next(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
loadVideoCategories () {
|
|
||||||
return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'categories', this.videoCategories, this.videoCategoriesLoaded, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadVideoLicences () {
|
|
||||||
return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'licences', this.videoLicences, this.videoLicencesLoaded)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadVideoLanguages () {
|
|
||||||
return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'languages', this.videoLanguages, this.videoLanguagesLoaded, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadVideoPrivacies () {
|
|
||||||
return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'privacies', this.videoPrivacies, this.videoPrivaciesLoaded)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadVideoPlaylistPrivacies () {
|
|
||||||
return this.loadAttributeEnum(
|
|
||||||
ServerService.BASE_VIDEO_PLAYLIST_URL,
|
|
||||||
'privacies',
|
|
||||||
this.videoPlaylistPrivacies,
|
|
||||||
this.videoPlaylistPrivaciesLoaded
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfig () {
|
|
||||||
return cloneDeep(this.config)
|
|
||||||
}
|
|
||||||
|
|
||||||
getServerVersionAndCommit () {
|
getServerVersionAndCommit () {
|
||||||
const serverVersion = this.config.serverVersion
|
const serverVersion = this.config.serverVersion
|
||||||
const commit = this.config.serverCommit || ''
|
const commit = this.config.serverCommit || ''
|
||||||
|
|
||||||
let result = `v${serverVersion}`
|
let result = serverVersion
|
||||||
if (commit) result += '...' + commit
|
if (commit) result += '...' + commit
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetConfig () {
|
||||||
|
this.configLoaded = false
|
||||||
|
this.configReset = true
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfig () {
|
||||||
|
if (this.configLoaded) return of(this.config)
|
||||||
|
|
||||||
|
if (!this.configObservable) {
|
||||||
|
this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL)
|
||||||
|
.pipe(
|
||||||
|
tap(this.saveConfigLocally),
|
||||||
|
tap(() => this.configLoaded = true),
|
||||||
|
tap(() => {
|
||||||
|
if (this.configReset) {
|
||||||
|
this.configReloaded.next()
|
||||||
|
this.configReset = false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
share()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.configObservable
|
||||||
|
}
|
||||||
|
|
||||||
|
getTmpConfig () {
|
||||||
|
return this.config
|
||||||
|
}
|
||||||
|
|
||||||
getVideoCategories () {
|
getVideoCategories () {
|
||||||
return cloneDeep(this.videoCategories)
|
if (!this.videoCategoriesObservable) {
|
||||||
|
this.videoCategoriesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'categories', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.videoCategoriesObservable.pipe(first())
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoLicences () {
|
getVideoLicences () {
|
||||||
return cloneDeep(this.videoLicences)
|
if (!this.videoLicensesObservable) {
|
||||||
|
this.videoLicensesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'licences')
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.videoLicensesObservable.pipe(first())
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoLanguages () {
|
getVideoLanguages () {
|
||||||
return cloneDeep(this.videoLanguages)
|
if (!this.videoLanguagesObservable) {
|
||||||
|
this.videoLanguagesObservable = this.loadAttributeEnum<string>(ServerService.BASE_VIDEO_URL, 'languages', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.videoLanguagesObservable.pipe(first())
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoPrivacies () {
|
getVideoPrivacies () {
|
||||||
return cloneDeep(this.videoPrivacies)
|
if (!this.videoPrivaciesObservable) {
|
||||||
|
this.videoPrivaciesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'privacies')
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.videoPrivaciesObservable.pipe(first())
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoPlaylistPrivacies () {
|
getVideoPlaylistPrivacies () {
|
||||||
return cloneDeep(this.videoPlaylistPrivacies)
|
if (!this.videoPlaylistPrivaciesObservable) {
|
||||||
}
|
this.videoPlaylistPrivaciesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_PLAYLIST_URL, 'privacies')
|
||||||
|
|
||||||
private loadAttributeEnum (
|
|
||||||
baseUrl: string,
|
|
||||||
attributeName: 'categories' | 'licences' | 'languages' | 'privacies',
|
|
||||||
hashToPopulate: VideoConstant<string | number>[],
|
|
||||||
notifier: ReplaySubject<boolean>,
|
|
||||||
sort = false
|
|
||||||
) {
|
|
||||||
this.localeObservable
|
|
||||||
.pipe(
|
|
||||||
switchMap(translations => {
|
|
||||||
return this.http.get<{ [id: string]: string }>(baseUrl + attributeName)
|
|
||||||
.pipe(map(data => ({ data, translations })))
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.subscribe(({ data, translations }) => {
|
|
||||||
Object.keys(data)
|
|
||||||
.forEach(dataKey => {
|
|
||||||
const label = data[ dataKey ]
|
|
||||||
|
|
||||||
hashToPopulate.push({
|
|
||||||
id: attributeName === 'languages' ? dataKey : parseInt(dataKey, 10),
|
|
||||||
label: peertubeTranslate(label, translations)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if (sort === true) sortBy(hashToPopulate, 'label')
|
|
||||||
|
|
||||||
notifier.next(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadServerLocale () {
|
|
||||||
const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId)
|
|
||||||
|
|
||||||
// Default locale, nothing to translate
|
|
||||||
if (isDefaultLocale(completeLocale)) {
|
|
||||||
this.localeObservable = of({}).pipe(shareReplay())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localeObservable = this.http
|
return this.videoPlaylistPrivaciesObservable.pipe(first())
|
||||||
.get(ServerService.BASE_LOCALE_URL + completeLocale + '/server.json')
|
}
|
||||||
.pipe(shareReplay())
|
|
||||||
|
getServerLocale () {
|
||||||
|
if (!this.localeObservable) {
|
||||||
|
const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId)
|
||||||
|
|
||||||
|
// Default locale, nothing to translate
|
||||||
|
if (isDefaultLocale(completeLocale)) {
|
||||||
|
this.localeObservable = of({}).pipe(shareReplay())
|
||||||
|
} else {
|
||||||
|
this.localeObservable = this.http
|
||||||
|
.get(ServerService.BASE_LOCALE_URL + completeLocale + '/server.json')
|
||||||
|
.pipe(shareReplay())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.localeObservable.pipe(first())
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadAttributeEnum <T extends string | number> (
|
||||||
|
baseUrl: string,
|
||||||
|
attributeName: 'categories' | 'licences' | 'languages' | 'privacies',
|
||||||
|
sort = false
|
||||||
|
) {
|
||||||
|
return this.getServerLocale()
|
||||||
|
.pipe(
|
||||||
|
switchMap(translations => {
|
||||||
|
return this.http.get<{ [ id: string ]: string }>(baseUrl + attributeName)
|
||||||
|
.pipe(map(data => ({ data, translations })))
|
||||||
|
}),
|
||||||
|
map(({ data, translations }) => {
|
||||||
|
const hashToPopulate: VideoConstant<T>[] = []
|
||||||
|
|
||||||
|
Object.keys(data)
|
||||||
|
.forEach(dataKey => {
|
||||||
|
const label = data[ dataKey ]
|
||||||
|
|
||||||
|
hashToPopulate.push({
|
||||||
|
id: (attributeName === 'languages' ? dataKey : parseInt(dataKey, 10)) as T,
|
||||||
|
label: peertubeTranslate(label, translations)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (sort === true) sortBy(hashToPopulate, 'label')
|
||||||
|
|
||||||
|
return hashToPopulate
|
||||||
|
}),
|
||||||
|
shareReplay()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveConfigLocally (config: ServerConfig) {
|
private saveConfigLocally (config: ServerConfig) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { AuthService } from '@app/core/auth'
|
||||||
import { ServerService } from '@app/core/server'
|
import { ServerService } from '@app/core/server'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { PluginService } from '@app/core/plugins/plugin.service'
|
import { PluginService } from '@app/core/plugins/plugin.service'
|
||||||
import { ServerConfigTheme } from '@shared/models'
|
import { ServerConfig, ServerConfigTheme } from '@shared/models'
|
||||||
import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
|
import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
|
||||||
import { first } from 'rxjs/operators'
|
import { first } from 'rxjs/operators'
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ export class ThemeService {
|
||||||
private themeFromLocalStorage: ServerConfigTheme
|
private themeFromLocalStorage: ServerConfigTheme
|
||||||
private themeDOMLinksFromLocalStorage: HTMLLinkElement[] = []
|
private themeDOMLinksFromLocalStorage: HTMLLinkElement[] = []
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private pluginService: PluginService,
|
private pluginService: PluginService,
|
||||||
|
@ -30,9 +32,12 @@ export class ThemeService {
|
||||||
// Try to load from local storage first, so we don't have to wait network requests
|
// Try to load from local storage first, so we don't have to wait network requests
|
||||||
this.loadAndSetFromLocalStorage()
|
this.loadAndSetFromLocalStorage()
|
||||||
|
|
||||||
this.server.configLoaded
|
this.serverConfig = this.server.getTmpConfig()
|
||||||
.subscribe(() => {
|
this.server.getConfig()
|
||||||
const themes = this.server.getConfig().theme.registered
|
.subscribe(config => {
|
||||||
|
this.serverConfig = config
|
||||||
|
|
||||||
|
const themes = this.serverConfig.theme.registered
|
||||||
|
|
||||||
this.removeThemeFromLocalStorageIfNeeded(themes)
|
this.removeThemeFromLocalStorageIfNeeded(themes)
|
||||||
this.injectThemes(themes)
|
this.injectThemes(themes)
|
||||||
|
@ -77,7 +82,7 @@ export class ThemeService {
|
||||||
if (theme !== 'instance-default') return theme
|
if (theme !== 'instance-default') return theme
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.server.getConfig().theme.default
|
return this.serverConfig.theme.default
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadTheme (name: string) {
|
private loadTheme (name: string) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ const loginRoutes: Routes = [
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
serverConfigLoaded: ServerConfigResolver
|
serverConfig: ServerConfigResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,7 +7,8 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service'
|
import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service'
|
||||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-login',
|
selector: 'my-login',
|
||||||
|
@ -23,10 +24,12 @@ export class LoginComponent extends FormReactive implements OnInit {
|
||||||
forgotPasswordEmail = ''
|
forgotPasswordEmail = ''
|
||||||
|
|
||||||
private openedForgotPasswordModal: NgbModalRef
|
private openedForgotPasswordModal: NgbModalRef
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public router: Router,
|
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute,
|
||||||
private modalService: NgbModal,
|
private modalService: NgbModal,
|
||||||
private loginValidatorsService: LoginValidatorsService,
|
private loginValidatorsService: LoginValidatorsService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
@ -40,14 +43,16 @@ export class LoginComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get signupAllowed () {
|
get signupAllowed () {
|
||||||
return this.serverService.getConfig().signup.allowed === true
|
return this.serverConfig.signup.allowed === true
|
||||||
}
|
}
|
||||||
|
|
||||||
isEmailDisabled () {
|
isEmailDisabled () {
|
||||||
return this.serverService.getConfig().email.enabled === false
|
return this.serverConfig.email.enabled === false
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.route.snapshot.data.serverConfig
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
username: this.loginValidatorsService.LOGIN_USERNAME,
|
username: this.loginValidatorsService.LOGIN_USERNAME,
|
||||||
password: this.loginValidatorsService.LOGIN_PASSWORD
|
password: this.loginValidatorsService.LOGIN_PASSWORD
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { AuthService, AuthStatus, RedirectService, ServerService, ThemeService }
|
||||||
import { User } from '../shared/users/user.model'
|
import { User } from '../shared/users/user.model'
|
||||||
import { LanguageChooserComponent } from '@app/menu/language-chooser.component'
|
import { LanguageChooserComponent } from '@app/menu/language-chooser.component'
|
||||||
import { HotkeysService } from 'angular2-hotkeys'
|
import { HotkeysService } from 'angular2-hotkeys'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-menu',
|
selector: 'my-menu',
|
||||||
|
@ -18,6 +19,7 @@ export class MenuComponent implements OnInit {
|
||||||
userHasAdminAccess = false
|
userHasAdminAccess = false
|
||||||
helpVisible = false
|
helpVisible = false
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
private routesPerRight: { [ role in UserRight ]?: string } = {
|
private routesPerRight: { [ role in UserRight ]?: string } = {
|
||||||
[UserRight.MANAGE_USERS]: '/admin/users',
|
[UserRight.MANAGE_USERS]: '/admin/users',
|
||||||
[UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
|
[UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
|
||||||
|
@ -36,6 +38,10 @@ export class MenuComponent implements OnInit {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.isLoggedIn = this.authService.isLoggedIn()
|
this.isLoggedIn = this.authService.isLoggedIn()
|
||||||
if (this.isLoggedIn === true) this.user = this.authService.getUser()
|
if (this.isLoggedIn === true) this.user = this.authService.getUser()
|
||||||
this.computeIsUserHasAdminAccess()
|
this.computeIsUserHasAdminAccess()
|
||||||
|
@ -64,8 +70,8 @@ export class MenuComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
isRegistrationAllowed () {
|
isRegistrationAllowed () {
|
||||||
return this.serverService.getConfig().signup.allowed &&
|
return this.serverConfig.signup.allowed &&
|
||||||
this.serverService.getConfig().signup.allowedForCurrentIP
|
this.serverConfig.signup.allowedForCurrentIP
|
||||||
}
|
}
|
||||||
|
|
||||||
getFirstAdminRightAvailable () {
|
getFirstAdminRightAvailable () {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core'
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||||
import { ValidatorFn } from '@angular/forms'
|
import { ValidatorFn } from '@angular/forms'
|
||||||
import { VideoValidatorsService } from '@app/shared'
|
import { VideoValidatorsService } from '@app/shared'
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { AdvancedSearch } from '@app/search/advanced-search.model'
|
import { AdvancedSearch } from '@app/search/advanced-search.model'
|
||||||
import { VideoConstant } from '../../../../shared'
|
import { ServerConfig, VideoConstant } from '../../../../shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-search-filters',
|
selector: 'my-search-filters',
|
||||||
|
@ -33,6 +33,8 @@ export class SearchFiltersComponent implements OnInit {
|
||||||
originallyPublishedStartYear: string
|
originallyPublishedStartYear: string
|
||||||
originallyPublishedEndYear: string
|
originallyPublishedEndYear: string
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private i18n: I18n,
|
private i18n: I18n,
|
||||||
private videoValidatorsService: VideoValidatorsService,
|
private videoValidatorsService: VideoValidatorsService,
|
||||||
|
@ -99,9 +101,13 @@ export class SearchFiltersComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.serverService.videoCategoriesLoaded.subscribe(() => this.videoCategories = this.serverService.getVideoCategories())
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
this.serverService.videoLicencesLoaded.subscribe(() => this.videoLicences = this.serverService.getVideoLicences())
|
this.serverService.getConfig()
|
||||||
this.serverService.videoLanguagesLoaded.subscribe(() => this.videoLanguages = this.serverService.getVideoLanguages())
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
|
this.serverService.getVideoCategories().subscribe(categories => this.videoCategories = categories)
|
||||||
|
this.serverService.getVideoLicences().subscribe(licences => this.videoLicences = licences)
|
||||||
|
this.serverService.getVideoLanguages().subscribe(languages => this.videoLanguages = languages)
|
||||||
|
|
||||||
this.loadFromDurationRange()
|
this.loadFromDurationRange()
|
||||||
this.loadFromPublishedRange()
|
this.loadFromPublishedRange()
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'
|
||||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
|
||||||
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
|
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-preview-upload',
|
selector: 'my-preview-upload',
|
||||||
|
@ -24,6 +25,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor {
|
||||||
imageSrc: SafeResourceUrl
|
imageSrc: SafeResourceUrl
|
||||||
allowedExtensionsMessage = ''
|
allowedExtensionsMessage = ''
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
private file: File
|
private file: File
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@ -32,14 +34,18 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get videoImageExtensions () {
|
get videoImageExtensions () {
|
||||||
return this.serverService.getConfig().video.image.extensions
|
return this.serverConfig.video.image.extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxVideoImageSize () {
|
get maxVideoImageSize () {
|
||||||
return this.serverService.getConfig().video.image.size.max
|
return this.serverConfig.video.image.size.max
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.allowedExtensionsMessage = this.videoImageExtensions.join(', ')
|
this.allowedExtensionsMessage = this.videoImageExtensions.join(', ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="feature-table">
|
<div class="feature-table">
|
||||||
|
|
||||||
<table class="table" *ngIf="config">
|
<table class="table" *ngIf="serverConfig">
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="label">PeerTube version</td>
|
<td i18n class="label">PeerTube version</td>
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="label">User registration allowed</td>
|
<td i18n class="label">User registration allowed</td>
|
||||||
<td>
|
<td>
|
||||||
<my-feature-boolean [value]="config.signup.allowed"></my-feature-boolean>
|
<my-feature-boolean [value]="serverConfig.signup.allowed"></my-feature-boolean>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -30,15 +30,15 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="sub-label">Transcoding in multiple resolutions</td>
|
<td i18n class="sub-label">Transcoding in multiple resolutions</td>
|
||||||
<td>
|
<td>
|
||||||
<my-feature-boolean [value]="config.transcoding.enabledResolutions.length !== 0"></my-feature-boolean>
|
<my-feature-boolean [value]="serverConfig.transcoding.enabledResolutions.length !== 0"></my-feature-boolean>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="sub-label">Video uploads</td>
|
<td i18n class="sub-label">Video uploads</td>
|
||||||
<td>
|
<td>
|
||||||
<span *ngIf="config.autoBlacklist.videos.ofUsers.enabled">Requires manual validation by moderators</span>
|
<span *ngIf="serverConfig.autoBlacklist.videos.ofUsers.enabled">Requires manual validation by moderators</span>
|
||||||
<span *ngIf="!config.autoBlacklist.videos.ofUsers.enabled">Automatically published</span>
|
<span *ngIf="!serverConfig.autoBlacklist.videos.ofUsers.enabled">Automatically published</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -69,14 +69,14 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="sub-label">HTTP import (YouTube, Vimeo, direct URL...)</td>
|
<td i18n class="sub-label">HTTP import (YouTube, Vimeo, direct URL...)</td>
|
||||||
<td>
|
<td>
|
||||||
<my-feature-boolean [value]="config.import.videos.http.enabled"></my-feature-boolean>
|
<my-feature-boolean [value]="serverConfig.import.videos.http.enabled"></my-feature-boolean>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="sub-label">Torrent import</td>
|
<td i18n class="sub-label">Torrent import</td>
|
||||||
<td>
|
<td>
|
||||||
<my-feature-boolean [value]="config.import.videos.torrent.enabled"></my-feature-boolean>
|
<my-feature-boolean [value]="serverConfig.import.videos.torrent.enabled"></my-feature-boolean>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td i18n class="sub-label">P2P enabled</td>
|
<td i18n class="sub-label">P2P enabled</td>
|
||||||
<td>
|
<td>
|
||||||
<my-feature-boolean [value]="config.tracker.enabled"></my-feature-boolean>
|
<my-feature-boolean [value]="serverConfig.tracker.enabled"></my-feature-boolean>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { ServerConfig } from '@shared/models'
|
||||||
})
|
})
|
||||||
export class InstanceFeaturesTableComponent implements OnInit {
|
export class InstanceFeaturesTableComponent implements OnInit {
|
||||||
quotaHelpIndication = ''
|
quotaHelpIndication = ''
|
||||||
config: ServerConfig
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private i18n: I18n,
|
private i18n: I18n,
|
||||||
|
@ -19,29 +19,34 @@ export class InstanceFeaturesTableComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get initialUserVideoQuota () {
|
get initialUserVideoQuota () {
|
||||||
return this.serverService.getConfig().user.videoQuota
|
return this.serverConfig.user.videoQuota
|
||||||
}
|
}
|
||||||
|
|
||||||
get dailyUserVideoQuota () {
|
get dailyUserVideoQuota () {
|
||||||
return Math.min(this.initialUserVideoQuota, this.serverService.getConfig().user.videoQuotaDaily)
|
return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily)
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.serverService.configLoaded
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
.subscribe(() => {
|
this.serverService.getConfig()
|
||||||
this.config = this.serverService.getConfig()
|
.subscribe(config => {
|
||||||
|
this.serverConfig = config
|
||||||
this.buildQuotaHelpIndication()
|
this.buildQuotaHelpIndication()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
buildNSFWLabel () {
|
buildNSFWLabel () {
|
||||||
const policy = this.serverService.getConfig().instance.defaultNSFWPolicy
|
const policy = this.serverConfig.instance.defaultNSFWPolicy
|
||||||
|
|
||||||
if (policy === 'do_not_list') return this.i18n('Hidden')
|
if (policy === 'do_not_list') return this.i18n('Hidden')
|
||||||
if (policy === 'blur') return this.i18n('Blurred with confirmation request')
|
if (policy === 'blur') return this.i18n('Blurred with confirmation request')
|
||||||
if (policy === 'display') return this.i18n('Displayed')
|
if (policy === 'display') return this.i18n('Displayed')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getServerVersionAndCommit () {
|
||||||
|
return this.serverService.getServerVersionAndCommit()
|
||||||
|
}
|
||||||
|
|
||||||
private getApproximateTime (seconds: number) {
|
private getApproximateTime (seconds: number) {
|
||||||
const hours = Math.floor(seconds / 3600)
|
const hours = Math.floor(seconds / 3600)
|
||||||
let pluralSuffix = ''
|
let pluralSuffix = ''
|
||||||
|
@ -53,10 +58,6 @@ export class InstanceFeaturesTableComponent implements OnInit {
|
||||||
return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes })
|
return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes })
|
||||||
}
|
}
|
||||||
|
|
||||||
getServerVersionAndCommit () {
|
|
||||||
return this.serverService.getServerVersionAndCommit()
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildQuotaHelpIndication () {
|
private buildQuotaHelpIndication () {
|
||||||
if (this.initialUserVideoQuota === -1) return
|
if (this.initialUserVideoQuota === -1) return
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { catchError } from 'rxjs/operators'
|
import { catchError, map } from 'rxjs/operators'
|
||||||
import { HttpClient } from '@angular/common/http'
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
|
@ -7,6 +7,7 @@ import { About } from '../../../../../shared/models/server'
|
||||||
import { MarkdownService } from '@app/shared/renderer'
|
import { MarkdownService } from '@app/shared/renderer'
|
||||||
import { peertubeTranslate } from '@shared/models'
|
import { peertubeTranslate } from '@shared/models'
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
|
import { forkJoin } from 'rxjs'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InstanceService {
|
export class InstanceService {
|
||||||
|
@ -57,25 +58,35 @@ export class InstanceService {
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTranslatedLanguages (about: About, translations: any) {
|
buildTranslatedLanguages (about: About) {
|
||||||
const languagesArray = this.serverService.getVideoLanguages()
|
return forkJoin([
|
||||||
|
this.serverService.getVideoLanguages(),
|
||||||
|
this.serverService.getServerLocale()
|
||||||
|
]).pipe(
|
||||||
|
map(([ languagesArray, translations ]) => {
|
||||||
|
return about.instance.languages
|
||||||
|
.map(l => {
|
||||||
|
const languageObj = languagesArray.find(la => la.id === l)
|
||||||
|
|
||||||
return about.instance.languages
|
return peertubeTranslate(languageObj.label, translations)
|
||||||
.map(l => {
|
})
|
||||||
const languageObj = languagesArray.find(la => la.id === l)
|
})
|
||||||
|
)
|
||||||
return peertubeTranslate(languageObj.label, translations)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTranslatedCategories (about: About, translations: any) {
|
buildTranslatedCategories (about: About) {
|
||||||
const categoriesArray = this.serverService.getVideoCategories()
|
return forkJoin([
|
||||||
|
this.serverService.getVideoCategories(),
|
||||||
|
this.serverService.getServerLocale()
|
||||||
|
]).pipe(
|
||||||
|
map(([ categoriesArray, translations ]) => {
|
||||||
|
return about.instance.categories
|
||||||
|
.map(c => {
|
||||||
|
const categoryObj = categoriesArray.find(ca => ca.id === c)
|
||||||
|
|
||||||
return about.instance.categories
|
return peertubeTranslate(categoryObj.label, translations)
|
||||||
.map(c => {
|
})
|
||||||
const categoryObj = categoriesArray.find(ca => ca.id === c)
|
})
|
||||||
|
)
|
||||||
return peertubeTranslate(categoryObj.label, translations)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
|
||||||
import { UserBanModalComponent } from '@app/shared/moderation/user-ban-modal.component'
|
import { UserBanModalComponent } from '@app/shared/moderation/user-ban-modal.component'
|
||||||
|
@ -7,12 +7,13 @@ import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core'
|
||||||
import { User, UserRight } from '../../../../../shared/models/users'
|
import { User, UserRight } from '../../../../../shared/models/users'
|
||||||
import { Account } from '@app/shared/account/account.model'
|
import { Account } from '@app/shared/account/account.model'
|
||||||
import { BlocklistService } from '@app/shared/blocklist'
|
import { BlocklistService } from '@app/shared/blocklist'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-user-moderation-dropdown',
|
selector: 'my-user-moderation-dropdown',
|
||||||
templateUrl: './user-moderation-dropdown.component.html'
|
templateUrl: './user-moderation-dropdown.component.html'
|
||||||
})
|
})
|
||||||
export class UserModerationDropdownComponent implements OnChanges {
|
export class UserModerationDropdownComponent implements OnInit, OnChanges {
|
||||||
@ViewChild('userBanModal', { static: false }) userBanModal: UserBanModalComponent
|
@ViewChild('userBanModal', { static: false }) userBanModal: UserBanModalComponent
|
||||||
|
|
||||||
@Input() user: User
|
@Input() user: User
|
||||||
|
@ -26,6 +27,8 @@ export class UserModerationDropdownComponent implements OnChanges {
|
||||||
|
|
||||||
userActions: DropdownAction<{ user: User, account: Account }>[][] = []
|
userActions: DropdownAction<{ user: User, account: Account }>[][] = []
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
|
@ -38,7 +41,13 @@ export class UserModerationDropdownComponent implements OnChanges {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
get requiresEmailVerification () {
|
get requiresEmailVerification () {
|
||||||
return this.serverService.getConfig().signup.requiresEmailVerification
|
return this.serverConfig.signup.requiresEmailVerification
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges () {
|
ngOnChanges () {
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class OverviewService {
|
||||||
.pipe(
|
.pipe(
|
||||||
// Translate categories
|
// Translate categories
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(translations => {
|
tap(translations => {
|
||||||
for (const c of videosOverviewResult.categories) {
|
for (const c of videosOverviewResult.categories) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class VideoCaptionService {
|
||||||
return this.authHttp.get<ResultList<VideoCaption>>(VideoService.BASE_VIDEO_URL + videoId + '/captions')
|
return this.authHttp.get<ResultList<VideoCaption>>(VideoService.BASE_VIDEO_URL + videoId + '/captions')
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(captionsResult => {
|
switchMap(captionsResult => {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(map(translations => ({ captionsResult, translations })))
|
.pipe(map(translations => ({ captionsResult, translations })))
|
||||||
}),
|
}),
|
||||||
map(({ captionsResult, translations }) => {
|
map(({ captionsResult, translations }) => {
|
||||||
|
|
|
@ -91,7 +91,7 @@ export class VideoImportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private extractVideoImports (result: ResultList<VideoImport>): Observable<ResultList<VideoImport>> {
|
private extractVideoImports (result: ResultList<VideoImport>): Observable<ResultList<VideoImport>> {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
map(translations => {
|
map(translations => {
|
||||||
result.data.forEach(d =>
|
result.data.forEach(d =>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
|
||||||
import { Video } from '@app/shared/video/video.model'
|
import { Video } from '@app/shared/video/video.model'
|
||||||
import { VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models'
|
import { ServerConfig, VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models'
|
||||||
import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core'
|
import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
@ -17,7 +17,7 @@ import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-
|
||||||
templateUrl: './video-playlist-element-miniature.component.html',
|
templateUrl: './video-playlist-element-miniature.component.html',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class VideoPlaylistElementMiniatureComponent {
|
export class VideoPlaylistElementMiniatureComponent implements OnInit {
|
||||||
@ViewChild('moreDropdown', { static: false }) moreDropdown: NgbDropdown
|
@ViewChild('moreDropdown', { static: false }) moreDropdown: NgbDropdown
|
||||||
|
|
||||||
@Input() playlist: VideoPlaylist
|
@Input() playlist: VideoPlaylist
|
||||||
|
@ -39,6 +39,8 @@ export class VideoPlaylistElementMiniatureComponent {
|
||||||
stopTimestamp: number
|
stopTimestamp: number
|
||||||
} = {} as any
|
} = {} as any
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
|
@ -51,6 +53,15 @@ export class VideoPlaylistElementMiniatureComponent {
|
||||||
private cdr: ChangeDetectorRef
|
private cdr: ChangeDetectorRef
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
ngOnInit (): void {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => {
|
||||||
|
this.serverConfig = config
|
||||||
|
this.cdr.detectChanges()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
isUnavailable (e: VideoPlaylistElement) {
|
isUnavailable (e: VideoPlaylistElement) {
|
||||||
return e.type === VideoPlaylistElementType.UNAVAILABLE
|
return e.type === VideoPlaylistElementType.UNAVAILABLE
|
||||||
}
|
}
|
||||||
|
@ -80,7 +91,7 @@ export class VideoPlaylistElementMiniatureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoBlur (video: Video) {
|
isVideoBlur (video: Video) {
|
||||||
return video.isVideoNSFWForUser(this.authService.getUser(), this.serverService.getConfig())
|
return video.isVideoNSFWForUser(this.authService.getUser(), this.serverConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFromPlaylist (playlistElement: VideoPlaylistElement) {
|
removeFromPlaylist (playlistElement: VideoPlaylistElement) {
|
||||||
|
|
|
@ -173,7 +173,7 @@ export class VideoPlaylistService {
|
||||||
}
|
}
|
||||||
|
|
||||||
extractPlaylists (result: ResultList<VideoPlaylistServerModel>) {
|
extractPlaylists (result: ResultList<VideoPlaylistServerModel>) {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
map(translations => {
|
map(translations => {
|
||||||
const playlistsJSON = result.data
|
const playlistsJSON = result.data
|
||||||
|
@ -190,12 +190,12 @@ export class VideoPlaylistService {
|
||||||
}
|
}
|
||||||
|
|
||||||
extractPlaylist (playlist: VideoPlaylistServerModel) {
|
extractPlaylist (playlist: VideoPlaylistServerModel) {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(map(translations => new VideoPlaylist(playlist, translations)))
|
.pipe(map(translations => new VideoPlaylist(playlist, translations)))
|
||||||
}
|
}
|
||||||
|
|
||||||
extractVideoPlaylistElements (result: ResultList<ServerVideoPlaylistElement>) {
|
extractVideoPlaylistElements (result: ResultList<ServerVideoPlaylistElement>) {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
map(translations => {
|
map(translations => {
|
||||||
const elementsJson = result.data
|
const elementsJson = result.data
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { Notifier, ServerService } from '@app/core'
|
||||||
import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
|
import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date'
|
import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date'
|
||||||
import { ResultList } from '@shared/models'
|
import { ResultList, ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
enum GroupDate {
|
enum GroupDate {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
|
@ -61,6 +61,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
|
||||||
|
|
||||||
onDataSubject = new Subject<any[]>()
|
onDataSubject = new Subject<any[]>()
|
||||||
|
|
||||||
|
protected serverConfig: ServerConfig
|
||||||
|
|
||||||
protected abstract notifier: Notifier
|
protected abstract notifier: Notifier
|
||||||
protected abstract authService: AuthService
|
protected abstract authService: AuthService
|
||||||
protected abstract route: ActivatedRoute
|
protected abstract route: ActivatedRoute
|
||||||
|
@ -85,6 +87,10 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.groupedDateLabels = {
|
this.groupedDateLabels = {
|
||||||
[GroupDate.UNKNOWN]: null,
|
[GroupDate.UNKNOWN]: null,
|
||||||
[GroupDate.TODAY]: this.i18n('Today'),
|
[GroupDate.TODAY]: this.i18n('Today'),
|
||||||
|
@ -251,7 +257,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = this.router.url
|
let path = this.router.url
|
||||||
if (!path || path === '/') path = this.serverService.getConfig().instance.defaultClientRoute
|
if (!path || path === '/') path = this.serverConfig.instance.defaultClientRoute
|
||||||
|
|
||||||
this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' })
|
this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' })
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, LOCALE
|
||||||
import { User } from '../users'
|
import { User } from '../users'
|
||||||
import { Video } from './video.model'
|
import { Video } from './video.model'
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
import { VideoPrivacy, VideoState } from '../../../../../shared'
|
import { ServerConfig, VideoPrivacy, VideoState } from '../../../../../shared'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { VideoActionsDisplayType } from '@app/shared/video/video-actions-dropdown.component'
|
import { VideoActionsDisplayType } from '@app/shared/video/video-actions-dropdown.component'
|
||||||
import { ScreenService } from '@app/shared/misc/screen.service'
|
import { ScreenService } from '@app/shared/misc/screen.service'
|
||||||
|
@ -55,6 +55,7 @@ export class VideoMiniatureComponent implements OnInit {
|
||||||
report: true
|
report: true
|
||||||
}
|
}
|
||||||
showActions = false
|
showActions = false
|
||||||
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
private ownerDisplayTypeChosen: 'account' | 'videoChannel'
|
private ownerDisplayTypeChosen: 'account' | 'videoChannel'
|
||||||
|
|
||||||
|
@ -66,10 +67,14 @@ export class VideoMiniatureComponent implements OnInit {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
get isVideoBlur () {
|
get isVideoBlur () {
|
||||||
return this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig())
|
return this.video.isVideoNSFWForUser(this.user, this.serverConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.setUpBy()
|
this.setUpBy()
|
||||||
|
|
||||||
// We rely on mouseenter to lazy load actions
|
// We rely on mouseenter to lazy load actions
|
||||||
|
|
|
@ -64,7 +64,7 @@ export class VideoService implements VideosProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideo (options: { videoId: string }): Observable<VideoDetails> {
|
getVideo (options: { videoId: string }): Observable<VideoDetails> {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(translations => {
|
switchMap(translations => {
|
||||||
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId)
|
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId)
|
||||||
|
@ -315,7 +315,7 @@ export class VideoService implements VideosProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
extractVideos (result: ResultList<VideoServerModel>) {
|
extractVideos (result: ResultList<VideoServerModel>) {
|
||||||
return this.serverService.localeObservable
|
return this.serverService.getServerLocale()
|
||||||
.pipe(
|
.pipe(
|
||||||
map(translations => {
|
map(translations => {
|
||||||
const videosJson = result.data
|
const videosJson = result.data
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validator
|
||||||
import { ServerService } from '@app/core'
|
import { ServerService } from '@app/core'
|
||||||
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
||||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { VideoConstant } from '../../../../../../shared'
|
import { ServerConfig, VideoConstant } from '../../../../../../shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-caption-add-modal',
|
selector: 'my-video-caption-add-modal',
|
||||||
|
@ -15,6 +15,7 @@ import { VideoConstant } from '../../../../../../shared'
|
||||||
|
|
||||||
export class VideoCaptionAddModalComponent extends FormReactive implements OnInit {
|
export class VideoCaptionAddModalComponent extends FormReactive implements OnInit {
|
||||||
@Input() existingCaptions: string[]
|
@Input() existingCaptions: string[]
|
||||||
|
@Input() serverConfig: ServerConfig
|
||||||
|
|
||||||
@Output() captionAdded = new EventEmitter<VideoCaptionEdit>()
|
@Output() captionAdded = new EventEmitter<VideoCaptionEdit>()
|
||||||
|
|
||||||
|
@ -35,15 +36,16 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
|
||||||
}
|
}
|
||||||
|
|
||||||
get videoCaptionExtensions () {
|
get videoCaptionExtensions () {
|
||||||
return this.serverService.getConfig().videoCaption.file.extensions
|
return this.serverConfig.videoCaption.file.extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
get videoCaptionMaxSize () {
|
get videoCaptionMaxSize () {
|
||||||
return this.serverService.getConfig().videoCaption.file.size.max
|
return this.serverConfig.videoCaption.file.size.max
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.videoCaptionLanguages = this.serverService.getVideoLanguages()
|
this.serverService.getVideoLanguages()
|
||||||
|
.subscribe(languages => this.videoCaptionLanguages = languages)
|
||||||
|
|
||||||
this.buildForm({
|
this.buildForm({
|
||||||
language: this.videoCaptionsValidatorsService.VIDEO_CAPTION_LANGUAGE,
|
language: this.videoCaptionsValidatorsService.VIDEO_CAPTION_LANGUAGE,
|
||||||
|
|
|
@ -269,5 +269,5 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<my-video-caption-add-modal
|
<my-video-caption-add-modal
|
||||||
#videoCaptionAddModal [existingCaptions]="existingCaptions" (captionAdded)="onCaptionAdded($event)"
|
#videoCaptionAddModal [existingCaptions]="existingCaptions" [serverConfig]="serverConfig" (captionAdded)="onCaptionAdded($event)"
|
||||||
></my-video-caption-add-modal>
|
></my-video-caption-add-modal>
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { VideoCaptionService } from '@app/shared/video-caption'
|
||||||
import { VideoCaptionAddModalComponent } from '@app/videos/+video-edit/shared/video-caption-add-modal.component'
|
import { VideoCaptionAddModalComponent } from '@app/videos/+video-edit/shared/video-caption-add-modal.component'
|
||||||
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
||||||
import { removeElementFromArray } from '@app/shared/misc/utils'
|
import { removeElementFromArray } from '@app/shared/misc/utils'
|
||||||
import { VideoConstant, VideoPrivacy } from '../../../../../../shared'
|
import { ServerConfig, VideoConstant, VideoPrivacy } from '../../../../../../shared'
|
||||||
import { VideoService } from '@app/shared/video/video.service'
|
import { VideoService } from '@app/shared/video/video.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -51,6 +51,8 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
||||||
calendarTimezone: string
|
calendarTimezone: string
|
||||||
calendarDateFormat: string
|
calendarDateFormat: string
|
||||||
|
|
||||||
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
private schedulerInterval: any
|
private schedulerInterval: any
|
||||||
private firstPatchDone = false
|
private firstPatchDone = false
|
||||||
private initialVideoCaptions: string[] = []
|
private initialVideoCaptions: string[] = []
|
||||||
|
@ -130,12 +132,19 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.updateForm()
|
this.updateForm()
|
||||||
|
|
||||||
this.videoCategories = this.serverService.getVideoCategories()
|
this.serverService.getVideoCategories()
|
||||||
this.videoLicences = this.serverService.getVideoLicences()
|
.subscribe(res => this.videoCategories = res)
|
||||||
this.videoLanguages = this.serverService.getVideoLanguages()
|
this.serverService.getVideoLicences()
|
||||||
|
.subscribe(res => this.videoLicences = res)
|
||||||
|
this.serverService.getVideoLanguages()
|
||||||
|
.subscribe(res => this.videoLanguages = res)
|
||||||
|
|
||||||
const privacies = this.serverService.getVideoPrivacies()
|
this.serverService.getVideoPrivacies()
|
||||||
this.videoPrivacies = this.videoService.explainedPrivacyLabels(privacies)
|
.subscribe(privacies => this.videoPrivacies = this.videoService.explainedPrivacyLabels(privacies))
|
||||||
|
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id)
|
this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { AuthService, Notifier, ServerService } from '@app/core'
|
import { AuthService, Notifier, ServerService } from '@app/core'
|
||||||
import { catchError, switchMap, tap } from 'rxjs/operators'
|
import { catchError, switchMap, tap } from 'rxjs/operators'
|
||||||
import { FormReactive } from '@app/shared'
|
import { FormReactive } from '@app/shared'
|
||||||
import { VideoConstant, VideoPrivacy } from '../../../../../../shared'
|
import { ServerConfig, VideoConstant, VideoPrivacy } from '../../../../../../shared'
|
||||||
import { VideoService } from '@app/shared/video/video.service'
|
import { VideoService } from '@app/shared/video/video.service'
|
||||||
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
|
||||||
import { VideoCaptionService } from '@app/shared/video-caption'
|
import { VideoCaptionService } from '@app/shared/video-caption'
|
||||||
|
@ -29,6 +29,7 @@ export abstract class VideoSend extends FormReactive implements OnInit {
|
||||||
protected serverService: ServerService
|
protected serverService: ServerService
|
||||||
protected videoService: VideoService
|
protected videoService: VideoService
|
||||||
protected videoCaptionService: VideoCaptionService
|
protected videoCaptionService: VideoCaptionService
|
||||||
|
protected serverConfig: ServerConfig
|
||||||
|
|
||||||
abstract canDeactivate (): CanComponentDeactivateResult
|
abstract canDeactivate (): CanComponentDeactivateResult
|
||||||
|
|
||||||
|
@ -38,10 +39,14 @@ export abstract class VideoSend extends FormReactive implements OnInit {
|
||||||
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
populateAsyncUserVideoChannels(this.authService, this.userVideoChannels)
|
||||||
.then(() => this.firstStepChannelId = this.userVideoChannels[ 0 ].id)
|
.then(() => this.firstStepChannelId = this.userVideoChannels[ 0 ].id)
|
||||||
|
|
||||||
this.serverService.videoPrivaciesLoaded
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
|
||||||
|
this.serverService.getVideoPrivacies()
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => {
|
privacies => {
|
||||||
this.videoPrivacies = this.serverService.getVideoPrivacies()
|
this.videoPrivacies = privacies
|
||||||
|
|
||||||
this.firstStepPrivacyId = this.DEFAULT_VIDEO_PRIVACY
|
this.firstStepPrivacyId = this.DEFAULT_VIDEO_PRIVACY
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.
|
||||||
import { FormValidatorService, UserService } from '@app/shared'
|
import { FormValidatorService, UserService } from '@app/shared'
|
||||||
import { VideoCaptionService } from '@app/shared/video-caption'
|
import { VideoCaptionService } from '@app/shared/video-caption'
|
||||||
import { scrollToTop } from '@app/shared/misc/utils'
|
import { scrollToTop } from '@app/shared/misc/utils'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-upload',
|
selector: 'my-video-upload',
|
||||||
|
@ -70,7 +71,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
}
|
}
|
||||||
|
|
||||||
get videoExtensions () {
|
get videoExtensions () {
|
||||||
return this.serverService.getConfig().video.file.extensions.join(',')
|
return this.serverConfig.video.file.extensions.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
@ -155,7 +156,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
}
|
}
|
||||||
|
|
||||||
const privacy = this.firstStepPrivacyId.toString()
|
const privacy = this.firstStepPrivacyId.toString()
|
||||||
const nsfw = this.serverService.getConfig().instance.isNSFW
|
const nsfw = this.serverConfig.instance.isNSFW
|
||||||
const waitTranscoding = true
|
const waitTranscoding = true
|
||||||
const commentsEnabled = true
|
const commentsEnabled = true
|
||||||
const downloadEnabled = true
|
const downloadEnabled = true
|
||||||
|
|
|
@ -1,28 +1,37 @@
|
||||||
import { Component, HostListener, ViewChild } from '@angular/core'
|
import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
|
||||||
import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service'
|
import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service'
|
||||||
import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component'
|
import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component'
|
||||||
import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component'
|
import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component'
|
||||||
import { AuthService, ServerService } from '@app/core'
|
import { AuthService, ServerService } from '@app/core'
|
||||||
import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component'
|
import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component'
|
||||||
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-videos-add',
|
selector: 'my-videos-add',
|
||||||
templateUrl: './video-add.component.html',
|
templateUrl: './video-add.component.html',
|
||||||
styleUrls: [ './video-add.component.scss' ]
|
styleUrls: [ './video-add.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideoAddComponent implements CanComponentDeactivate {
|
export class VideoAddComponent implements OnInit, CanComponentDeactivate {
|
||||||
@ViewChild('videoUpload', { static: false }) videoUpload: VideoUploadComponent
|
@ViewChild('videoUpload', { static: false }) videoUpload: VideoUploadComponent
|
||||||
@ViewChild('videoImportUrl', { static: false }) videoImportUrl: VideoImportUrlComponent
|
@ViewChild('videoImportUrl', { static: false }) videoImportUrl: VideoImportUrlComponent
|
||||||
@ViewChild('videoImportTorrent', { static: false }) videoImportTorrent: VideoImportTorrentComponent
|
@ViewChild('videoImportTorrent', { static: false }) videoImportTorrent: VideoImportTorrentComponent
|
||||||
|
|
||||||
secondStepType: 'upload' | 'import-url' | 'import-torrent'
|
secondStepType: 'upload' | 'import-url' | 'import-torrent'
|
||||||
videoName: string
|
videoName: string
|
||||||
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private serverService: ServerService
|
private serverService: ServerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
|
|
||||||
|
this.serverService.getConfig()
|
||||||
|
.subscribe(config => this.serverConfig = config)
|
||||||
|
}
|
||||||
|
|
||||||
onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) {
|
onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) {
|
||||||
this.secondStepType = type
|
this.secondStepType = type
|
||||||
this.videoName = videoName
|
this.videoName = videoName
|
||||||
|
@ -52,11 +61,11 @@ export class VideoAddComponent implements CanComponentDeactivate {
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoImportHttpEnabled () {
|
isVideoImportHttpEnabled () {
|
||||||
return this.serverService.getConfig().import.videos.http.enabled
|
return this.serverConfig.import.videos.http.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoImportTorrentEnabled () {
|
isVideoImportTorrentEnabled () {
|
||||||
return this.serverService.getConfig().import.videos.torrent.enabled
|
return this.serverConfig.import.videos.torrent.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
isInSecondStep () {
|
isInSecondStep () {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { MetaService } from '@ngx-meta/core'
|
||||||
import { AuthUser, Notifier, ServerService } from '@app/core'
|
import { AuthUser, Notifier, ServerService } from '@app/core'
|
||||||
import { forkJoin, Observable, Subscription } from 'rxjs'
|
import { forkJoin, Observable, Subscription } from 'rxjs'
|
||||||
import { Hotkey, HotkeysService } from 'angular2-hotkeys'
|
import { Hotkey, HotkeysService } from 'angular2-hotkeys'
|
||||||
import { UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared'
|
import { ServerConfig, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared'
|
||||||
import { AuthService, ConfirmService } from '../../core'
|
import { AuthService, ConfirmService } from '../../core'
|
||||||
import { RestExtractor, VideoBlacklistService } from '../../shared'
|
import { RestExtractor, VideoBlacklistService } from '../../shared'
|
||||||
import { VideoDetails } from '../../shared/video/video-details.model'
|
import { VideoDetails } from '../../shared/video/video-details.model'
|
||||||
|
@ -84,6 +84,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
private queryParamsSub: Subscription
|
private queryParamsSub: Subscription
|
||||||
private configSub: Subscription
|
private configSub: Subscription
|
||||||
|
|
||||||
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private elementRef: ElementRef,
|
private elementRef: ElementRef,
|
||||||
private changeDetector: ChangeDetectorRef,
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
@ -120,11 +122,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.configSub = this.serverService.configLoaded
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
.subscribe(() => {
|
|
||||||
|
this.configSub = this.serverService.getConfig()
|
||||||
|
.subscribe(config => {
|
||||||
|
this.serverConfig = config
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isWebRTCDisabled() ||
|
isWebRTCDisabled() ||
|
||||||
this.serverService.getConfig().tracker.enabled === false ||
|
this.serverConfig.tracker.enabled === false ||
|
||||||
peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true'
|
peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true'
|
||||||
) {
|
) {
|
||||||
this.hasAlreadyAcceptedPrivacyConcern = true
|
this.hasAlreadyAcceptedPrivacyConcern = true
|
||||||
|
@ -280,7 +286,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoBlur (video: Video) {
|
isVideoBlur (video: Video) {
|
||||||
return video.isVideoNSFWForUser(this.user, this.serverService.getConfig())
|
return video.isVideoNSFWForUser(this.user, this.serverConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
isAutoPlayEnabled () {
|
isAutoPlayEnabled () {
|
||||||
|
|
|
@ -40,11 +40,8 @@ export class VideoMostLikedComponent extends AbstractVideoList implements OnInit
|
||||||
|
|
||||||
this.generateSyndicationList()
|
this.generateSyndicationList()
|
||||||
|
|
||||||
this.serverService.configLoaded.subscribe(
|
this.titlePage = this.i18n('Most liked videos')
|
||||||
() => {
|
this.titleTooltip = this.i18n('Videos that have the higher number of likes.')
|
||||||
this.titlePage = this.i18n('Most liked videos')
|
|
||||||
this.titleTooltip = this.i18n('Videos that have the higher number of likes.')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideosObservable (page: number) {
|
getVideosObservable (page: number) {
|
||||||
|
|
|
@ -40,9 +40,9 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
|
||||||
|
|
||||||
this.generateSyndicationList()
|
this.generateSyndicationList()
|
||||||
|
|
||||||
this.serverService.configLoaded.subscribe(
|
this.serverService.getConfig().subscribe(
|
||||||
() => {
|
config => {
|
||||||
const trendingDays = this.serverService.getConfig().trending.videos.intervalDays
|
const trendingDays = config.trending.videos.intervalDays
|
||||||
|
|
||||||
if (trendingDays === 1) {
|
if (trendingDays === 1) {
|
||||||
this.titlePage = this.i18n('Trending for the last 24 hours')
|
this.titlePage = this.i18n('Trending for the last 24 hours')
|
||||||
|
|
|
@ -8,6 +8,6 @@ else
|
||||||
clientCommand="npm run build:client"
|
clientCommand="npm run build:client"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
npm run concurrently -- --raw \
|
npm run concurrently -- --raw \w
|
||||||
"$clientCommand" \
|
"$clientCommand" \
|
||||||
"npm run build:server"
|
"npm run build:server"
|
||||||
|
|
Loading…
Reference in New Issue