Add ability to change the homepage
This commit is contained in:
parent
a73c582e5b
commit
901637bb87
18 changed files with 108 additions and 18 deletions
|
@ -37,6 +37,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="instanceDefaultClientRoute">Default client route</label>
|
||||
<div class="peertube-select-container">
|
||||
<select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
|
||||
<option value="/videos/trending">Videos Trending</option>
|
||||
<option value="/videos/recently-added">Videos Recently Added</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inner-form-title">Cache</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -46,6 +46,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
instanceName: '',
|
||||
instanceDescription: '',
|
||||
instanceTerms: '',
|
||||
instanceDefaultClientRoute: '',
|
||||
cachePreviewsSize: '',
|
||||
signupLimit: '',
|
||||
adminEmail: '',
|
||||
|
@ -85,6 +86,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
instanceName: [ '', INSTANCE_NAME.VALIDATORS ],
|
||||
instanceDescription: [ '' ],
|
||||
instanceTerms: [ '' ],
|
||||
instanceDefaultClientRoute: [ '' ],
|
||||
cachePreviewsSize: [ '', CACHE_PREVIEWS_SIZE.VALIDATORS ],
|
||||
signupEnabled: [ ],
|
||||
signupLimit: [ '', SIGNUP_LIMIT.VALIDATORS ],
|
||||
|
@ -153,11 +155,12 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
if (confirmRes === false) return
|
||||
}
|
||||
|
||||
const data = {
|
||||
const data: CustomConfig = {
|
||||
instance: {
|
||||
name: this.form.value['instanceName'],
|
||||
description: this.form.value['instanceDescription'],
|
||||
terms: this.form.value['instanceTerms'],
|
||||
defaultClientRoute: this.form.value['instanceDefaultClientRoute'],
|
||||
customizations: {
|
||||
javascript: this.form.value['customizationJavascript'],
|
||||
css: this.form.value['customizationCSS']
|
||||
|
@ -213,6 +216,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
instanceName: this.customConfig.instance.name,
|
||||
instanceDescription: this.customConfig.instance.description,
|
||||
instanceTerms: this.customConfig.instance.terms,
|
||||
instanceDefaultClientRoute: this.customConfig.instance.defaultClientRoute,
|
||||
cachePreviewsSize: this.customConfig.cache.previews.size,
|
||||
signupEnabled: this.customConfig.signup.enabled,
|
||||
signupLimit: this.customConfig.signup.limit,
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
import { RedirectService } from '@app/core/routing/redirect.service'
|
||||
|
||||
import { PreloadSelectedModulesList } from './core'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/videos/trending',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: './+admin/admin.module#AdminModule'
|
||||
|
@ -22,7 +18,9 @@ const routes: Routes = [
|
|||
preloadingStrategy: PreloadSelectedModulesList
|
||||
})
|
||||
],
|
||||
providers: [ PreloadSelectedModulesList ],
|
||||
providers: [
|
||||
PreloadSelectedModulesList
|
||||
],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
|
||||
import { GuardsCheckStart, Router } from '@angular/router'
|
||||
import { AuthService, ServerService } from '@app/core'
|
||||
import { AuthService, RedirectService, ServerService } from '@app/core'
|
||||
import { isInSmallView } from '@app/shared/misc/utils'
|
||||
|
||||
@Component({
|
||||
|
@ -31,7 +31,8 @@ export class AppComponent implements OnInit {
|
|||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private serverService: ServerService,
|
||||
private domSanitizer: DomSanitizer
|
||||
private domSanitizer: DomSanitizer,
|
||||
private redirectService: RedirectService
|
||||
) {}
|
||||
|
||||
get serverVersion () {
|
||||
|
@ -43,6 +44,10 @@ export class AppComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnInit () {
|
||||
if (this.router.url === '/') {
|
||||
this.redirectService.redirectToHomepage()
|
||||
}
|
||||
|
||||
this.authService.loadClientCredentials()
|
||||
|
||||
if (this.authService.isLoggedIn()) {
|
||||
|
|
|
@ -13,7 +13,7 @@ import { ModalModule } from 'ngx-bootstrap/modal'
|
|||
import { AuthService } from './auth'
|
||||
import { ConfirmComponent, ConfirmService } from './confirm'
|
||||
import { throwIfAlreadyLoaded } from './module-import-guard'
|
||||
import { LoginGuard, UserRightGuard } from './routing'
|
||||
import { LoginGuard, RedirectService, UserRightGuard } from './routing'
|
||||
import { ServerService } from './server'
|
||||
|
||||
@NgModule({
|
||||
|
@ -48,7 +48,8 @@ import { ServerService } from './server'
|
|||
ConfirmService,
|
||||
ServerService,
|
||||
LoginGuard,
|
||||
UserRightGuard
|
||||
UserRightGuard,
|
||||
RedirectService
|
||||
]
|
||||
})
|
||||
export class CoreModule {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './login-guard.service'
|
||||
export * from './user-right-guard.service'
|
||||
export * from './preload-selected-modules-list'
|
||||
export * from './redirect.service'
|
||||
|
|
48
client/src/app/core/routing/redirect.service.ts
Normal file
48
client/src/app/core/routing/redirect.service.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { ServerService } from '../server'
|
||||
|
||||
@Injectable()
|
||||
export class RedirectService {
|
||||
// Default route could change according to the instance configuration
|
||||
static INIT_DEFAULT_ROUTE = '/videos/trending'
|
||||
static DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE
|
||||
|
||||
constructor (
|
||||
private router: Router,
|
||||
private serverService: ServerService
|
||||
) {
|
||||
// The config is first loaded from the cache so try to get the default route
|
||||
const config = this.serverService.getConfig()
|
||||
if (config && config.instance && config.instance.defaultClientRoute) {
|
||||
RedirectService.DEFAULT_ROUTE = config.instance.defaultClientRoute
|
||||
}
|
||||
|
||||
this.serverService.configLoaded
|
||||
.subscribe(() => {
|
||||
const defaultRouteConfig = this.serverService.getConfig().instance.defaultClientRoute
|
||||
|
||||
if (defaultRouteConfig) {
|
||||
RedirectService.DEFAULT_ROUTE = defaultRouteConfig
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
redirectToHomepage () {
|
||||
console.log('Redirecting to %s...', RedirectService.DEFAULT_ROUTE)
|
||||
|
||||
this.router.navigate([ RedirectService.DEFAULT_ROUTE ])
|
||||
.catch(() => {
|
||||
console.error(
|
||||
'Cannot navigate to %s, resetting default route to %s.',
|
||||
RedirectService.DEFAULT_ROUTE,
|
||||
RedirectService.INIT_DEFAULT_ROUTE
|
||||
)
|
||||
|
||||
RedirectService.DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE
|
||||
return this.router.navigate([ RedirectService.DEFAULT_ROUTE ])
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ export class ServerService {
|
|||
private config: ServerConfig = {
|
||||
instance: {
|
||||
name: 'PeerTube',
|
||||
defaultClientRoute: '',
|
||||
customizations: {
|
||||
javascript: '',
|
||||
css: ''
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { RedirectService } from '@app/core/routing/redirect.service'
|
||||
import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
|
||||
import { MetaService } from '@ngx-meta/core'
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import { Subscription } from 'rxjs/Subscription'
|
||||
import * as videojs from 'video.js'
|
||||
import 'videojs-hotkeys'
|
||||
|
@ -64,7 +64,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
private authService: AuthService,
|
||||
private notificationsService: NotificationsService,
|
||||
private markdownService: MarkdownService,
|
||||
private zone: NgZone
|
||||
private zone: NgZone,
|
||||
private redirectService: RedirectService
|
||||
) {}
|
||||
|
||||
get user () {
|
||||
|
@ -142,7 +143,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
.subscribe(
|
||||
status => {
|
||||
this.notificationsService.success('Success', `Video ${this.video.name} had been blacklisted.`)
|
||||
this.router.navigate(['/videos/list'])
|
||||
this.redirectService.redirectToHomepage()
|
||||
},
|
||||
|
||||
error => this.notificationsService.error('Error', error.message)
|
||||
|
@ -247,7 +248,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
this.notificationsService.success('Success', `Video ${this.video.name} deleted.`)
|
||||
|
||||
// Go back to the video-list.
|
||||
this.router.navigate([ '/videos/list' ])
|
||||
this.redirectService.redirectToHomepage()
|
||||
},
|
||||
|
||||
error => this.notificationsService.error('Error', error.message)
|
||||
|
@ -313,7 +314,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
'This video contains mature or explicit content. Are you sure you want to watch it?',
|
||||
'Mature or explicit content'
|
||||
)
|
||||
if (res === false) return this.router.navigate([ '/videos/list' ])
|
||||
if (res === false) return this.redirectService.redirectToHomepage()
|
||||
}
|
||||
|
||||
if (!this.hasAlreadyAcceptedPrivacyConcern()) {
|
||||
|
@ -323,7 +324,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
'Privacy concern',
|
||||
'I accept!'
|
||||
)
|
||||
if (res === false) return this.router.navigate([ '/videos/list' ])
|
||||
if (res === false) return this.redirectService.redirectToHomepage()
|
||||
}
|
||||
|
||||
this.acceptedPrivacyConcern()
|
||||
|
|
|
@ -74,6 +74,7 @@ instance:
|
|||
name: 'PeerTube'
|
||||
description: 'Welcome to this PeerTube instance!' # Support markdown
|
||||
terms: 'No terms for now.' # Support markdown
|
||||
default_client_route: '/videos/trending'
|
||||
customizations:
|
||||
javascript: '' # Directly your JavaScript code (without <script> tags). Will be eval at runtime
|
||||
css: '' # Directly your CSS code (without <style> tags). Will be injected at runtime
|
||||
|
|
|
@ -87,6 +87,7 @@ instance:
|
|||
name: 'PeerTube'
|
||||
description: '' # Support markdown
|
||||
terms: '' # Support markdown
|
||||
default_client_route: '/videos/trending'
|
||||
customizations:
|
||||
javascript: '' # Directly your JavaScript code (without <script> tags). Will be eval at runtime
|
||||
css: '' # Directly your CSS code (without <style> tags). Will be injected at runtime
|
||||
|
|
|
@ -44,6 +44,7 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
|
|||
const json: ServerConfig = {
|
||||
instance: {
|
||||
name: CONFIG.INSTANCE.NAME,
|
||||
defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
|
||||
customizations: {
|
||||
javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT,
|
||||
css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS
|
||||
|
@ -114,7 +115,9 @@ async function updateCustomConfig (req: express.Request, res: express.Response,
|
|||
// Need to change the videoQuota key a little bit
|
||||
const toUpdateJSON = omit(toUpdate, 'videoQuota')
|
||||
toUpdateJSON.user['video_quota'] = toUpdate.user.videoQuota
|
||||
toUpdateJSON.instance['default_client_route'] = toUpdate.instance.defaultClientRoute
|
||||
delete toUpdate.user.videoQuota
|
||||
delete toUpdate.instance.defaultClientRoute
|
||||
|
||||
await writeFilePromise(CONFIG.CUSTOM_FILE, JSON.stringify(toUpdateJSON, undefined, 2))
|
||||
|
||||
|
@ -138,6 +141,7 @@ function customConfig (): CustomConfig {
|
|||
name: CONFIG.INSTANCE.NAME,
|
||||
description: CONFIG.INSTANCE.DESCRIPTION,
|
||||
terms: CONFIG.INSTANCE.TERMS,
|
||||
defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
|
||||
customizations: {
|
||||
css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS,
|
||||
javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT
|
||||
|
|
|
@ -159,6 +159,7 @@ const CONFIG = {
|
|||
get NAME () { return config.get<string>('instance.name') },
|
||||
get DESCRIPTION () { return config.get<string>('instance.description') },
|
||||
get TERMS () { return config.get<string>('instance.terms') },
|
||||
get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
|
||||
CUSTOMIZATIONS: {
|
||||
get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') },
|
||||
get CSS () { return config.get<string>('instance.customizations.css') }
|
||||
|
|
|
@ -5,6 +5,12 @@ import { logger } from '../../helpers/logger'
|
|||
import { areValidationErrors } from './utils'
|
||||
|
||||
const customConfigUpdateValidator = [
|
||||
body('instance.name').exists().withMessage('Should have a valid instance name'),
|
||||
body('instance.description').exists().withMessage('Should have a valid instance description'),
|
||||
body('instance.terms').exists().withMessage('Should have a valid instance terms'),
|
||||
body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'),
|
||||
body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'),
|
||||
body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'),
|
||||
body('cache.previews.size').isInt().withMessage('Should have a valid previews size'),
|
||||
body('signup.enabled').isBoolean().withMessage('Should have a valid signup enabled boolean'),
|
||||
body('signup.limit').isInt().withMessage('Should have a valid signup limit'),
|
||||
|
|
|
@ -18,6 +18,7 @@ describe('Test config API validators', function () {
|
|||
name: 'PeerTube updated',
|
||||
description: 'my super description',
|
||||
terms: 'my super terms',
|
||||
defaultClientRoute: '/videos/recently-added',
|
||||
customizations: {
|
||||
javascript: 'alert("coucou")',
|
||||
css: 'body { background-color: red; }'
|
||||
|
|
|
@ -54,6 +54,7 @@ describe('Test config', function () {
|
|||
expect(data.instance.name).to.equal('PeerTube')
|
||||
expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
|
||||
expect(data.instance.terms).to.equal('No terms for now.')
|
||||
expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
|
||||
expect(data.instance.customizations.css).to.be.empty
|
||||
expect(data.instance.customizations.javascript).to.be.empty
|
||||
expect(data.cache.previews.size).to.equal(1)
|
||||
|
@ -76,6 +77,7 @@ describe('Test config', function () {
|
|||
name: 'PeerTube updated',
|
||||
description: 'my super description',
|
||||
terms: 'my super terms',
|
||||
defaultClientRoute: '/videos/recently-added',
|
||||
customizations: {
|
||||
javascript: 'alert("coucou")',
|
||||
css: 'body { background-color: red; }'
|
||||
|
@ -116,6 +118,7 @@ describe('Test config', function () {
|
|||
expect(data.instance.name).to.equal('PeerTube updated')
|
||||
expect(data.instance.description).to.equal('my super description')
|
||||
expect(data.instance.terms).to.equal('my super terms')
|
||||
expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
|
||||
expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
|
||||
expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
|
||||
expect(data.cache.previews.size).to.equal(2)
|
||||
|
@ -145,6 +148,7 @@ describe('Test config', function () {
|
|||
expect(data.instance.name).to.equal('PeerTube updated')
|
||||
expect(data.instance.description).to.equal('my super description')
|
||||
expect(data.instance.terms).to.equal('my super terms')
|
||||
expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
|
||||
expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
|
||||
expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
|
||||
expect(data.cache.previews.size).to.equal(2)
|
||||
|
@ -181,6 +185,7 @@ describe('Test config', function () {
|
|||
expect(data.instance.name).to.equal('PeerTube')
|
||||
expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
|
||||
expect(data.instance.terms).to.equal('No terms for now.')
|
||||
expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
|
||||
expect(data.instance.customizations.css).to.be.empty
|
||||
expect(data.instance.customizations.javascript).to.be.empty
|
||||
expect(data.cache.previews.size).to.equal(1)
|
||||
|
|
|
@ -3,6 +3,7 @@ export interface CustomConfig {
|
|||
name: string
|
||||
description: string
|
||||
terms: string
|
||||
defaultClientRoute: string
|
||||
customizations: {
|
||||
javascript?: string
|
||||
css?: string
|
||||
|
|
|
@ -2,7 +2,8 @@ export interface ServerConfig {
|
|||
serverVersion: string
|
||||
|
||||
instance: {
|
||||
name: string;
|
||||
name: string
|
||||
defaultClientRoute: string
|
||||
customizations: {
|
||||
javascript: string
|
||||
css: string
|
||||
|
|
Loading…
Reference in a new issue