Properly scroll to anchors in links, especially in admin config
This commit is contained in:
parent
111fdc267b
commit
45e0d6697c
|
@ -96,9 +96,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div id="statistics" i18n class="middle-title">
|
<div class="anchor" id="statistics"></div>
|
||||||
STATISTICS
|
<div i18n class="middle-title">STATISTICS</div>
|
||||||
</div>
|
|
||||||
<my-instance-statistics></my-instance-statistics>
|
<my-instance-statistics></my-instance-statistics>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import { Component, OnInit, ViewChild } from '@angular/core'
|
import { Component, OnInit, ViewChild, AfterViewChecked } from '@angular/core'
|
||||||
import { Notifier, ServerService } from '@app/core'
|
import { Notifier, ServerService } from '@app/core'
|
||||||
import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
|
import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
|
||||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||||
import { ServerConfig } from '@shared/models'
|
import { ServerConfig } from '@shared/models'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
import { ResolverData } from './about-instance.resolver'
|
import { ResolverData } from './about-instance.resolver'
|
||||||
|
import { ViewportScroller } from '@angular/common'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-about-instance',
|
selector: 'my-about-instance',
|
||||||
templateUrl: './about-instance.component.html',
|
templateUrl: './about-instance.component.html',
|
||||||
styleUrls: [ './about-instance.component.scss' ]
|
styleUrls: [ './about-instance.component.scss' ]
|
||||||
})
|
})
|
||||||
export class AboutInstanceComponent implements OnInit {
|
export class AboutInstanceComponent implements OnInit, AfterViewChecked {
|
||||||
@ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
|
@ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
|
||||||
|
|
||||||
shortDescription = ''
|
shortDescription = ''
|
||||||
|
@ -35,8 +36,8 @@ export class AboutInstanceComponent implements OnInit {
|
||||||
serverConfig: ServerConfig
|
serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
private viewportScroller: ViewportScroller,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private notifier: Notifier,
|
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private instanceService: InstanceService
|
private instanceService: InstanceService
|
||||||
) {}
|
) {}
|
||||||
|
@ -72,6 +73,10 @@ export class AboutInstanceComponent implements OnInit {
|
||||||
this.html = await this.instanceService.buildHtml(about)
|
this.html = await this.instanceService.buildHtml(about)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewChecked () {
|
||||||
|
if (window.location.hash) this.viewportScroller.scrollToAnchor(window.location.hash.replace('#', ''))
|
||||||
|
}
|
||||||
|
|
||||||
openContactModal () {
|
openContactModal () {
|
||||||
return this.contactAdminModal.show()
|
return this.contactAdminModal.show()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<form role="form" [formGroup]="form">
|
<form role="form" [formGroup]="form">
|
||||||
|
|
||||||
<ngb-tabset class="root-tabset bootstrap">
|
<ngb-tabset #tabs class="root-tabset bootstrap">
|
||||||
|
|
||||||
<ngb-tab i18n-title title="Instance information">
|
<ngb-tab id="instance-information" i18n-title title="Instance information">
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
|
|
||||||
<ng-container formGroupName="instance">
|
<ng-container formGroupName="instance">
|
||||||
|
@ -210,7 +210,7 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceHardwareInformation">What server/hardware does the instance run on?</label>
|
<label i18n for="instanceHardwareInformation">What server/hardware does the instance run on?</label>
|
||||||
<div i18n class="label-small-info">2vCore 2GB RAM/or directly the link to the server you rent etc</div>
|
<div i18n class="label-small-info">i.e. 2vCore 2GB RAM, a direct the link to the server you rent, etc.</div>
|
||||||
|
|
||||||
<my-markdown-textarea
|
<my-markdown-textarea
|
||||||
name="instanceHardwareInformation" formControlName="hardwareInformation" textareaWidth="500px" textareaHeight="75px" [previewColumn]="true"
|
name="instanceHardwareInformation" formControlName="hardwareInformation" textareaWidth="500px" textareaHeight="75px" [previewColumn]="true"
|
||||||
|
@ -227,14 +227,14 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
|
|
||||||
<ngb-tab i18n-title title="Basic configuration">
|
<ngb-tab id="basic-configuration" i18n-title title="Basic configuration">
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
|
|
||||||
<div class="form-row mt-5"> <!-- appearance grid -->
|
<div class="form-row mt-5"> <!-- appearance grid -->
|
||||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||||
<div i18n class="inner-form-title">APPEARANCE</div>
|
<div i18n class="inner-form-title">APPEARANCE</div>
|
||||||
<div i18n class="inner-for-description">
|
<div i18n class="inner-for-description">
|
||||||
Use <a routerLink="/admin/plugins">plugins & themes</a> for more involved changes.
|
Use <a routerLink="/admin/plugins">plugins & themes</a> for more involved changes, or <a routerLink="/admin/config/edit-custom" fragment="customizations" (click)="gotoAnchor()">add slight customizations</a>.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -391,6 +391,9 @@
|
||||||
<div class="form-row mt-4"> <!-- federation grid -->
|
<div class="form-row mt-4"> <!-- federation grid -->
|
||||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||||
<div i18n class="inner-form-title">FEDERATION</div>
|
<div i18n class="inner-form-title">FEDERATION</div>
|
||||||
|
<div i18n class="inner-form-description">
|
||||||
|
Manage <a routerLink="/admin/follows">relations</a> with other instances.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
|
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
|
||||||
|
@ -489,7 +492,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
|
|
||||||
<ngb-tab i18n-title title="Services">
|
<ngb-tab id="services" i18n-title title="Services">
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
|
|
||||||
<div class="form-row mt-5"> <!-- twitter grid -->
|
<div class="form-row mt-5"> <!-- twitter grid -->
|
||||||
|
@ -542,7 +545,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
|
|
||||||
<ngb-tab i18n-title title="Advanced configuration">
|
<ngb-tab id="advanced-configuration" i18n-title title="Advanced configuration">
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
|
|
||||||
<div class="form-row mt-5"> <!-- transcoding grid -->
|
<div class="form-row mt-5"> <!-- transcoding grid -->
|
||||||
|
@ -718,6 +721,7 @@
|
||||||
|
|
||||||
<div class="form-row mt-4"> <!-- cache grid -->
|
<div class="form-row mt-4"> <!-- cache grid -->
|
||||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||||
|
<div class="anchor" id="customizations"></div> <!-- customizations anchor -->
|
||||||
<div i18n class="inner-form-title">CUSTOMIZATIONS</div>
|
<div i18n class="inner-form-title">CUSTOMIZATIONS</div>
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Slight modifications to your PeerTube instance for when creating a plugin or theme is overkill.
|
Slight modifications to your PeerTube instance for when creating a plugin or theme is overkill.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, AfterViewChecked, ViewChild } from '@angular/core'
|
||||||
import { ConfigService } from '@app/+admin/config/shared/config.service'
|
import { ConfigService } from '@app/+admin/config/shared/config.service'
|
||||||
import { ServerService } from '@app/core/server/server.service'
|
import { ServerService } from '@app/core/server/server.service'
|
||||||
import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } from '@app/shared'
|
import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } from '@app/shared'
|
||||||
|
@ -9,13 +9,18 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val
|
||||||
import { SelectItem } from 'primeng/api'
|
import { SelectItem } from 'primeng/api'
|
||||||
import { forkJoin } from 'rxjs'
|
import { forkJoin } from 'rxjs'
|
||||||
import { ServerConfig } from '@shared/models'
|
import { ServerConfig } from '@shared/models'
|
||||||
|
import { ViewportScroller } from '@angular/common'
|
||||||
|
import { NgbTabset } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-edit-custom-config',
|
selector: 'my-edit-custom-config',
|
||||||
templateUrl: './edit-custom-config.component.html',
|
templateUrl: './edit-custom-config.component.html',
|
||||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||||
})
|
})
|
||||||
export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
export class EditCustomConfigComponent extends FormReactive implements OnInit, AfterViewChecked {
|
||||||
|
@ViewChild('tabs') private tabs: NgbTabset
|
||||||
|
|
||||||
|
initDone = false
|
||||||
customConfig: CustomConfig
|
customConfig: CustomConfig
|
||||||
|
|
||||||
resolutions: { id: string, label: string, description?: string }[] = []
|
resolutions: { id: string, label: string, description?: string }[] = []
|
||||||
|
@ -27,6 +32,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
private serverConfig: ServerConfig
|
private serverConfig: ServerConfig
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
private viewportScroller: ViewportScroller,
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
private customConfigValidatorsService: CustomConfigValidatorsService,
|
private customConfigValidatorsService: CustomConfigValidatorsService,
|
||||||
private userValidatorsService: UserValidatorsService,
|
private userValidatorsService: UserValidatorsService,
|
||||||
|
@ -226,6 +232,13 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
this.checkTranscodingFields()
|
this.checkTranscodingFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewChecked () {
|
||||||
|
if (!this.initDone) {
|
||||||
|
this.initDone = true
|
||||||
|
this.gotoAnchor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isTranscodingEnabled () {
|
isTranscodingEnabled () {
|
||||||
return this.form.value['transcoding']['enabled'] === true
|
return this.form.value['transcoding']['enabled'] === true
|
||||||
}
|
}
|
||||||
|
@ -272,6 +285,18 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
return this.i18n('No category')
|
return this.i18n('No category')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gotoAnchor () {
|
||||||
|
const hashToTab = {
|
||||||
|
'customizations': 'advanced-configuration'
|
||||||
|
}
|
||||||
|
const hash = window.location.hash.replace('#', '')
|
||||||
|
|
||||||
|
if (hash && Object.keys(hashToTab).includes(hash)) {
|
||||||
|
this.tabs.select(hashToTab[hash])
|
||||||
|
setTimeout(() => this.viewportScroller.scrollToAnchor(hash), 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private updateForm () {
|
private updateForm () {
|
||||||
this.form.patchValue(this.customConfig)
|
this.form.patchValue(this.customConfig)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
<div class="form-row mt-5"> <!-- notifications grid -->
|
<div class="form-row mt-5"> <!-- notifications grid -->
|
||||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||||
|
<div class="anchor" id="notifications"></div> <!-- notifications anchor -->
|
||||||
<div i18n class="account-title">NOTIFICATIONS</div>
|
<div i18n class="account-title">NOTIFICATIONS</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { Component, OnInit, AfterViewChecked } from '@angular/core'
|
||||||
import { Notifier } from '@app/core'
|
import { Notifier } from '@app/core'
|
||||||
import { BytesPipe } from 'ngx-pipes'
|
import { BytesPipe } from 'ngx-pipes'
|
||||||
import { AuthService } from '../../core'
|
import { AuthService } from '../../core'
|
||||||
import { User } from '../../shared'
|
import { User } from '../../shared'
|
||||||
import { UserService } from '../../shared/users'
|
import { UserService } from '../../shared/users'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
import { ViewportScroller } from '@angular/common'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-account-settings',
|
selector: 'my-account-settings',
|
||||||
templateUrl: './my-account-settings.component.html',
|
templateUrl: './my-account-settings.component.html',
|
||||||
styleUrls: [ './my-account-settings.component.scss' ]
|
styleUrls: [ './my-account-settings.component.scss' ]
|
||||||
})
|
})
|
||||||
export class MyAccountSettingsComponent implements OnInit {
|
export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
|
||||||
user: User = null
|
user: User = null
|
||||||
|
|
||||||
userVideoQuota = '0'
|
userVideoQuota = '0'
|
||||||
|
@ -21,6 +22,7 @@ export class MyAccountSettingsComponent implements OnInit {
|
||||||
userVideoQuotaUsedDaily = 0
|
userVideoQuotaUsedDaily = 0
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
private viewportScroller: ViewportScroller,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
|
@ -57,6 +59,10 @@ export class MyAccountSettingsComponent implements OnInit {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewChecked () {
|
||||||
|
if (window.location.hash) this.viewportScroller.scrollToAnchor(window.location.hash.replace('#', ''))
|
||||||
|
}
|
||||||
|
|
||||||
onAvatarChange (formData: FormData) {
|
onAvatarChange (formData: FormData) {
|
||||||
this.userService.changeAvatar(formData)
|
this.userService.changeAvatar(formData)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
|
|
|
@ -246,6 +246,11 @@ table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.anchor {
|
||||||
|
position: relative;
|
||||||
|
top: #{-($header-height + 20px)};
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: #{map-get($grid-breakpoints, xxl)}) {
|
@media screen and (max-width: #{map-get($grid-breakpoints, xxl)}) {
|
||||||
.main-col {
|
.main-col {
|
||||||
&.expanded {
|
&.expanded {
|
||||||
|
|
Loading…
Reference in New Issue