]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Properly scroll to anchors in links, especially in admin config
authorRigel Kent <sendmemail@rigelk.eu>
Wed, 11 Mar 2020 18:38:17 +0000 (19:38 +0100)
committerRigel Kent <sendmemail@rigelk.eu>
Wed, 11 Mar 2020 18:38:17 +0000 (19:38 +0100)
client/src/app/+about/about-instance/about-instance.component.html
client/src/app/+about/about-instance/about-instance.component.ts
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
client/src/app/+my-account/my-account-settings/my-account-settings.component.html
client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
client/src/sass/application.scss

index 043f633541056e99a727ffae12923aadcdf9cb06..1df1ef2ad6befba64aa14b89fca04b96c0f35743 100644 (file)
@@ -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>
index c8c1561054c0de160c39903bde137860c0329c30..e1809d7b7f57cc63ba18e1a9a266e238a4f052dd 100644 (file)
@@ -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()
   }
index be89d8294bed1dfc43dfcc314a315460dfc8d7df..b3b4f7728603568d2ef46d1ade53eb3c2dacaaa3 100644 (file)
@@ -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">
 
               <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"
       </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>
 
         <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">
       </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 -->
     </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 -->
 
         <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.
index c88e81c01453e0ce56961a276e715a5f5acf51b1..c3eac68bbf419474aa73826577d49da65e021b6d 100644 (file)
@@ -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)
   }
index 164afb4ea329137580641e3a672059baa9fa087c..87296bc19da70645b8b3b7dfc2027642de200acf 100644 (file)
@@ -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>
 
index e314cdbeac9c1ee75b0d3c73d246f2b7369ad635..ada98401c754af9b82a9a7746d26bcfcf1ba3a52 100644 (file)
@@ -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(
index f76a822434092f032ecc86d4775eb3868ab9fcaa..89957704b319906cfd5a2ccd95e6f9bc0d28d69f 100644 (file)
@@ -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 {