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 class="col">
|
||||
<div id="statistics" i18n class="middle-title">
|
||||
STATISTICS
|
||||
</div>
|
||||
<div class="anchor" id="statistics"></div>
|
||||
<div i18n class="middle-title">STATISTICS</div>
|
||||
<my-instance-statistics></my-instance-statistics>
|
||||
</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 { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
|
||||
import { InstanceService } from '@app/shared/instance/instance.service'
|
||||
import { ServerConfig } from '@shared/models'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { ResolverData } from './about-instance.resolver'
|
||||
import { ViewportScroller } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-about-instance',
|
||||
templateUrl: './about-instance.component.html',
|
||||
styleUrls: [ './about-instance.component.scss' ]
|
||||
})
|
||||
export class AboutInstanceComponent implements OnInit {
|
||||
export class AboutInstanceComponent implements OnInit, AfterViewChecked {
|
||||
@ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
|
||||
|
||||
shortDescription = ''
|
||||
|
@ -35,8 +36,8 @@ export class AboutInstanceComponent implements OnInit {
|
|||
serverConfig: ServerConfig
|
||||
|
||||
constructor (
|
||||
private viewportScroller: ViewportScroller,
|
||||
private route: ActivatedRoute,
|
||||
private notifier: Notifier,
|
||||
private serverService: ServerService,
|
||||
private instanceService: InstanceService
|
||||
) {}
|
||||
|
@ -72,6 +73,10 @@ export class AboutInstanceComponent implements OnInit {
|
|||
this.html = await this.instanceService.buildHtml(about)
|
||||
}
|
||||
|
||||
ngAfterViewChecked () {
|
||||
if (window.location.hash) this.viewportScroller.scrollToAnchor(window.location.hash.replace('#', ''))
|
||||
}
|
||||
|
||||
openContactModal () {
|
||||
return this.contactAdminModal.show()
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<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-container formGroupName="instance">
|
||||
|
@ -210,7 +210,7 @@
|
|||
|
||||
<div class="form-group">
|
||||
<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
|
||||
name="instanceHardwareInformation" formControlName="hardwareInformation" textareaWidth="500px" textareaHeight="75px" [previewColumn]="true"
|
||||
|
@ -227,14 +227,14 @@
|
|||
</ng-template>
|
||||
</ngb-tab>
|
||||
|
||||
<ngb-tab i18n-title title="Basic configuration">
|
||||
<ngb-tab id="basic-configuration" i18n-title title="Basic configuration">
|
||||
<ng-template ngbTabContent>
|
||||
|
||||
<div class="form-row mt-5"> <!-- appearance grid -->
|
||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||
<div i18n class="inner-form-title">APPEARANCE</div>
|
||||
<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>
|
||||
|
||||
|
@ -391,6 +391,9 @@
|
|||
<div class="form-row mt-4"> <!-- federation grid -->
|
||||
<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-description">
|
||||
Manage <a routerLink="/admin/follows">relations</a> with other instances.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
|
||||
|
@ -489,7 +492,7 @@
|
|||
</ng-template>
|
||||
</ngb-tab>
|
||||
|
||||
<ngb-tab i18n-title title="Services">
|
||||
<ngb-tab id="services" i18n-title title="Services">
|
||||
<ng-template ngbTabContent>
|
||||
|
||||
<div class="form-row mt-5"> <!-- twitter grid -->
|
||||
|
@ -542,7 +545,7 @@
|
|||
</ng-template>
|
||||
</ngb-tab>
|
||||
|
||||
<ngb-tab i18n-title title="Advanced configuration">
|
||||
<ngb-tab id="advanced-configuration" i18n-title title="Advanced configuration">
|
||||
<ng-template ngbTabContent>
|
||||
|
||||
<div class="form-row mt-5"> <!-- transcoding grid -->
|
||||
|
@ -718,6 +721,7 @@
|
|||
|
||||
<div class="form-row mt-4"> <!-- cache grid -->
|
||||
<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-description">
|
||||
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 { ServerService } from '@app/core/server/server.service'
|
||||
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 { forkJoin } from 'rxjs'
|
||||
import { ServerConfig } from '@shared/models'
|
||||
import { ViewportScroller } from '@angular/common'
|
||||
import { NgbTabset } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-custom-config',
|
||||
templateUrl: './edit-custom-config.component.html',
|
||||
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
|
||||
|
||||
resolutions: { id: string, label: string, description?: string }[] = []
|
||||
|
@ -27,6 +32,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
private serverConfig: ServerConfig
|
||||
|
||||
constructor (
|
||||
private viewportScroller: ViewportScroller,
|
||||
protected formValidatorService: FormValidatorService,
|
||||
private customConfigValidatorsService: CustomConfigValidatorsService,
|
||||
private userValidatorsService: UserValidatorsService,
|
||||
|
@ -226,6 +232,13 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
this.checkTranscodingFields()
|
||||
}
|
||||
|
||||
ngAfterViewChecked () {
|
||||
if (!this.initDone) {
|
||||
this.initDone = true
|
||||
this.gotoAnchor()
|
||||
}
|
||||
}
|
||||
|
||||
isTranscodingEnabled () {
|
||||
return this.form.value['transcoding']['enabled'] === true
|
||||
}
|
||||
|
@ -272,6 +285,18 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
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 () {
|
||||
this.form.patchValue(this.customConfig)
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
<div class="form-row mt-5"> <!-- notifications grid -->
|
||||
<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>
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { Component, OnInit, AfterViewChecked } from '@angular/core'
|
||||
import { Notifier } from '@app/core'
|
||||
import { BytesPipe } from 'ngx-pipes'
|
||||
import { AuthService } from '../../core'
|
||||
import { User } from '../../shared'
|
||||
import { UserService } from '../../shared/users'
|
||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||
import { ViewportScroller } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-settings',
|
||||
templateUrl: './my-account-settings.component.html',
|
||||
styleUrls: [ './my-account-settings.component.scss' ]
|
||||
})
|
||||
export class MyAccountSettingsComponent implements OnInit {
|
||||
export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
|
||||
user: User = null
|
||||
|
||||
userVideoQuota = '0'
|
||||
|
@ -21,6 +22,7 @@ export class MyAccountSettingsComponent implements OnInit {
|
|||
userVideoQuotaUsedDaily = 0
|
||||
|
||||
constructor (
|
||||
private viewportScroller: ViewportScroller,
|
||||
private userService: UserService,
|
||||
private authService: AuthService,
|
||||
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) {
|
||||
this.userService.changeAvatar(formData)
|
||||
.subscribe(
|
||||
|
|
|
@ -246,6 +246,11 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.anchor {
|
||||
position: relative;
|
||||
top: #{-($header-height + 20px)};
|
||||
}
|
||||
|
||||
@media screen and (max-width: #{map-get($grid-breakpoints, xxl)}) {
|
||||
.main-col {
|
||||
&.expanded {
|
||||
|
|
Loading…
Reference in New Issue