aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
authorKimsible <1877318+kimsible@users.noreply.github.com>2020-11-17 14:04:44 +0100
committerGitHub <noreply@github.com>2020-11-17 14:04:44 +0100
commitf3081d6401b63da41b03376f9f952bf1cca8303d (patch)
tree90ec91babde1544ca0a3423b031c9e10dfcac596 /client
parent901c36d5f44e02436da5f5c2899666329ff2eb5b (diff)
downloadPeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.tar.gz
PeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.tar.zst
PeerTube-f3081d6401b63da41b03376f9f952bf1cca8303d.zip
small refactor + clipboard copy on anchor click in instance page (#3318)
* Refacto scrollTo top and anchors * Add on click clipboard copy and notifier to anchors about/instance page * Fix margin top anchor middle title about page * Use viewportscroller for scrolltoanchor * Add to Link copied notification on instance page Co-authored-by: kimsible <kimsible@users.noreply.github.com>
Diffstat (limited to 'client')
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.html100
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.scss4
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.ts10
-rw-r--r--client/src/app/app.component.ts2
-rw-r--r--client/src/app/helpers/utils.ts8
-rw-r--r--client/src/app/menu/menu.component.html13
-rw-r--r--client/src/app/menu/menu.component.ts14
-rw-r--r--client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts7
8 files changed, 117 insertions, 41 deletions
diff --git a/client/src/app/+about/about-instance/about-instance.component.html b/client/src/app/+about/about-instance/about-instance.component.html
index d759c4343..045bb3fbc 100644
--- a/client/src/app/+about/about-instance/about-instance.component.html
+++ b/client/src/app/+about/about-instance/about-instance.component.html
@@ -23,7 +23,10 @@
23 <a 23 <a
24 *ngIf="html.administrator || maintenanceLifetime || businessModel" 24 *ngIf="html.administrator || maintenanceLifetime || businessModel"
25 class="anchor-link" 25 class="anchor-link"
26 routerLink="/about/instance" fragment="administrators-and-sustainability" 26 routerLink="/about/instance"
27 fragment="administrators-and-sustainability"
28 #anchorLink
29 (click)="onClickCopyLink(anchorLink)"
27 > 30 >
28 <h2 i18n class="middle-title"> 31 <h2 i18n class="middle-title">
29 ADMINISTRATORS & SUSTAINABILITY 32 ADMINISTRATORS & SUSTAINABILITY
@@ -32,7 +35,12 @@
32 35
33 <div class="block administrator" *ngIf="html.administrator"> 36 <div class="block administrator" *ngIf="html.administrator">
34 <div class="anchor" id="administrators"></div> 37 <div class="anchor" id="administrators"></div>
35 <a class="anchor-link" routerLink="/about/instance" fragment="administrators"> 38 <a
39 class="anchor-link"
40 routerLink="/about/instance"
41 fragment="administrators"
42 #anchorLink
43 (click)="onClickCopyLink(anchorLink)">
36 <h3 i18n class="section-title">Who we are</h3> 44 <h3 i18n class="section-title">Who we are</h3>
37 </a> 45 </a>
38 46
@@ -41,7 +49,12 @@
41 49
42 <div class="block creation-reason" *ngIf="creationReason"> 50 <div class="block creation-reason" *ngIf="creationReason">
43 <div class="anchor" id="creation-reason"></div> 51 <div class="anchor" id="creation-reason"></div>
44 <a class="anchor-link" routerLink="/about/instance" fragment="creation-reason"> 52 <a
53 class="anchor-link"
54 routerLink="/about/instance"
55 fragment="creation-reason"
56 #anchorLink
57 (click)="onClickCopyLink(anchorLink)">
45 <h3 i18n class="section-title">Why we created this instance</h3> 58 <h3 i18n class="section-title">Why we created this instance</h3>
46 </a> 59 </a>
47 60
@@ -50,7 +63,12 @@
50 63
51 <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime"> 64 <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime">
52 <div class="anchor" id="maintenance-lifetime"></div> 65 <div class="anchor" id="maintenance-lifetime"></div>
53 <a class="anchor-link" routerLink="/about/instance" fragment="maintenance-lifetime"> 66 <a
67 class="anchor-link"
68 routerLink="/about/instance"
69 fragment="maintenance-lifetime"
70 #anchorLink
71 (click)="onClickCopyLink(anchorLink)">
54 <h3 i18n class="section-title">How long we plan to maintain this instance</h3> 72 <h3 i18n class="section-title">How long we plan to maintain this instance</h3>
55 </a> 73 </a>
56 74
@@ -58,8 +76,13 @@
58 </div> 76 </div>
59 77
60 <div class="block business-model" *ngIf="businessModel"> 78 <div class="block business-model" *ngIf="businessModel">
61 <div class="anchor" id="buisiness-model"></div> 79 <div class="anchor" id="business-model"></div>
62 <a class="anchor-link" routerLink="/about/instance" fragment="buisiness-model"> 80 <a
81 class="anchor-link"
82 routerLink="/about/instance"
83 fragment="business-model"
84 #anchorLink
85 (click)="onClickCopyLink(anchorLink)">
63 <h3 i18n class="section-title">How we will pay for this instance</h3> 86 <h3 i18n class="section-title">How we will pay for this instance</h3>
64 </a> 87 </a>
65 88
@@ -67,7 +90,13 @@
67 </div> 90 </div>
68 91
69 <div class="anchor" id="information"></div> 92 <div class="anchor" id="information"></div>
70 <a *ngIf="html.description" class="anchor-link" routerLink="/about/instance" fragment="information"> 93 <a
94 *ngIf="html.description"
95 class="anchor-link"
96 routerLink="/about/instance"
97 fragment="information"
98 #anchorLink
99 (click)="onClickCopyLink(anchorLink)">
71 <h2 i18n class="middle-title"> 100 <h2 i18n class="middle-title">
72 INFORMATION 101 INFORMATION
73 </h2> 102 </h2>
@@ -75,7 +104,12 @@
75 104
76 <div class="block description"> 105 <div class="block description">
77 <div class="anchor" id="description"></div> 106 <div class="anchor" id="description"></div>
78 <a class="anchor-link" routerLink="/about/instance" fragment="description"> 107 <a
108 class="anchor-link"
109 routerLink="/about/instance"
110 fragment="description"
111 #anchorLink
112 (click)="onClickCopyLink(anchorLink)">
79 <h3 i18n class="section-title">Description</h3> 113 <h3 i18n class="section-title">Description</h3>
80 </a> 114 </a>
81 115
@@ -85,8 +119,11 @@
85 <div class="anchor" id="moderation"></div> 119 <div class="anchor" id="moderation"></div>
86 <a 120 <a
87 *ngIf="html.moderationInformation || html.codeOfConduct || html.terms" 121 *ngIf="html.moderationInformation || html.codeOfConduct || html.terms"
88 class="anchor-link" routerLink="/about/instance" fragment="moderation" 122 class="anchor-link"
89 > 123 routerLink="/about/instance"
124 fragment="moderation"
125 #anchorLink
126 (click)="onClickCopyLink(anchorLink)">
90 <h2 i18n class="middle-title"> 127 <h2 i18n class="middle-title">
91 MODERATION 128 MODERATION
92 </h2> 129 </h2>
@@ -94,7 +131,12 @@
94 131
95 <div class="block moderation-information" *ngIf="html.moderationInformation"> 132 <div class="block moderation-information" *ngIf="html.moderationInformation">
96 <div class="anchor" id="moderation-information"></div> 133 <div class="anchor" id="moderation-information"></div>
97 <a class="anchor-link" routerLink="/about/instance" fragment="moderation-information"> 134 <a
135 class="anchor-link"
136 routerLink="/about/instance"
137 fragment="moderation-information"
138 #anchorLink
139 (click)="onClickCopyLink(anchorLink)">
98 <h3 i18n class="section-title">Moderation information</h3> 140 <h3 i18n class="section-title">Moderation information</h3>
99 </a> 141 </a>
100 142
@@ -103,7 +145,12 @@
103 145
104 <div class="block code-of-conduct" *ngIf="html.codeOfConduct"> 146 <div class="block code-of-conduct" *ngIf="html.codeOfConduct">
105 <div class="anchor" id="code-of-conduct"></div> 147 <div class="anchor" id="code-of-conduct"></div>
106 <a class="anchor-link" routerLink="/about/instance" fragment="code-of-conduct"> 148 <a
149 class="anchor-link"
150 routerLink="/about/instance"
151 fragment="code-of-conduct"
152 #anchorLink
153 (click)="onClickCopyLink(anchorLink)">
107 <h3 i18n class="section-title">Code of conduct</h3> 154 <h3 i18n class="section-title">Code of conduct</h3>
108 </a> 155 </a>
109 156
@@ -112,7 +159,12 @@
112 159
113 <div class="block terms"> 160 <div class="block terms">
114 <div class="anchor" id="terms"></div> 161 <div class="anchor" id="terms"></div>
115 <a class="anchor-link" routerLink="/about/instance" fragment="terms"> 162 <a
163 class="anchor-link"
164 routerLink="/about/instance"
165 fragment="terms"
166 #anchorLink
167 (click)="onClickCopyLink(anchorLink)">
116 <h3 i18n class="section-title">Terms</h3> 168 <h3 i18n class="section-title">Terms</h3>
117 </a> 169 </a>
118 170
@@ -120,7 +172,13 @@
120 </div> 172 </div>
121 173
122 <div class="anchor" id="other-information"></div> 174 <div class="anchor" id="other-information"></div>
123 <a *ngIf="html.hardwareInformation" class="anchor-link" routerLink="/about/instance" fragment="other-information"> 175 <a
176 *ngIf="html.hardwareInformation"
177 class="anchor-link"
178 routerLink="/about/instance"
179 fragment="other-information"
180 #anchorLink
181 (click)="onClickCopyLink(anchorLink)">
124 <h2 i18n class="middle-title"> 182 <h2 i18n class="middle-title">
125 OTHER INFORMATION 183 OTHER INFORMATION
126 </h2> 184 </h2>
@@ -128,7 +186,12 @@
128 186
129 <div class="block hardware-information" *ngIf="html.hardwareInformation"> 187 <div class="block hardware-information" *ngIf="html.hardwareInformation">
130 <div class="anchor" id="hardware-information"></div> 188 <div class="anchor" id="hardware-information"></div>
131 <a class="anchor-link" routerLink="/about/instance" fragment="hardware-information"> 189 <a
190 class="anchor-link"
191 routerLink="/about/instance"
192 fragment="hardware-information"
193 #anchorLink
194 (click)="onClickCopyLink(anchorLink)">
132 <h3 i18n class="section-title">Hardware information</h3> 195 <h3 i18n class="section-title">Hardware information</h3>
133 </a> 196 </a>
134 197
@@ -143,7 +206,12 @@
143 206
144 <div class="col"> 207 <div class="col">
145 <div class="anchor" id="statistics"></div> 208 <div class="anchor" id="statistics"></div>
146 <a class="anchor-link" routerLink="/about/instance" fragment="statistics"> 209 <a
210 class="anchor-link"
211 routerLink="/about/instance"
212 fragment="statistics"
213 #anchorLink
214 (click)="onClickCopyLink(anchorLink)">
147 <h2 i18n class="middle-title">STATISTICS</h2> 215 <h2 i18n class="middle-title">STATISTICS</h2>
148 </a> 216 </a>
149 <my-instance-statistics></my-instance-statistics> 217 <my-instance-statistics></my-instance-statistics>
diff --git a/client/src/app/+about/about-instance/about-instance.component.scss b/client/src/app/+about/about-instance/about-instance.component.scss
index 2e77ade9b..fe3ce22b0 100644
--- a/client/src/app/+about/about-instance/about-instance.component.scss
+++ b/client/src/app/+about/about-instance/about-instance.component.scss
@@ -43,12 +43,12 @@
43.middle-title { 43.middle-title {
44 @include in-content-small-title; 44 @include in-content-small-title;
45 45
46 margin-top: 45px; 46 margin-top: 0;
47 margin-bottom: 25px; 47 margin-bottom: 25px;
48} 48}
49 49
50.block { 50.block {
51 margin-bottom: 30px; 51 margin-bottom: 75px;
52 font-size: 15px; 52 font-size: 15px;
53} 53}
54 54
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts
index bd587fa26..e74b5daeb 100644
--- a/client/src/app/+about/about-instance/about-instance.component.ts
+++ b/client/src/app/+about/about-instance/about-instance.component.ts
@@ -2,7 +2,8 @@ import { ViewportScroller } from '@angular/common'
2import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core' 2import { AfterViewChecked, Component, OnInit, ViewChild } from '@angular/core'
3import { ActivatedRoute } from '@angular/router' 3import { ActivatedRoute } from '@angular/router'
4import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component' 4import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
5import { ServerService } from '@app/core' 5import { Notifier } from '@app/core'
6import { copyToClipboard } from '../../../assets/player/utils'
6import { InstanceService } from '@app/shared/shared-instance' 7import { InstanceService } from '@app/shared/shared-instance'
7import { ServerConfig } from '@shared/models' 8import { ServerConfig } from '@shared/models'
8import { ResolverData } from './about-instance.resolver' 9import { ResolverData } from './about-instance.resolver'
@@ -42,6 +43,7 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
42 constructor ( 43 constructor (
43 private viewportScroller: ViewportScroller, 44 private viewportScroller: ViewportScroller,
44 private route: ActivatedRoute, 45 private route: ActivatedRoute,
46 private notifier: Notifier,
45 private instanceService: InstanceService 47 private instanceService: InstanceService
46 ) {} 48 ) {}
47 49
@@ -87,4 +89,10 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
87 openContactModal () { 89 openContactModal () {
88 return this.contactAdminModal.show() 90 return this.contactAdminModal.show()
89 } 91 }
92
93 onClickCopyLink (anchor: HTMLAnchorElement) {
94 const link = anchor.href
95 copyToClipboard(link)
96 this.notifier.success(link, $localize `Link copied`)
97 }
90} 98}
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index edec3216e..da51040ad 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -121,7 +121,7 @@ export class AppComponent implements OnInit, AfterViewInit {
121 // scrollToAnchor first to preserve anchor position when using history navigation 121 // scrollToAnchor first to preserve anchor position when using history navigation
122 if (e.anchor) { 122 if (e.anchor) {
123 setTimeout(() => { 123 setTimeout(() => {
124 document.getElementById(e.anchor).scrollIntoView({ behavior: 'smooth', inline: 'nearest' }) 124 this.viewportScroller.scrollToAnchor(e.anchor)
125 }) 125 })
126 126
127 return 127 return
diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts
index d9007dd77..a22507f46 100644
--- a/client/src/app/helpers/utils.ts
+++ b/client/src/app/helpers/utils.ts
@@ -144,8 +144,12 @@ function sortBy (obj: any[], key1: string, key2?: string) {
144 }) 144 })
145} 145}
146 146
147function scrollToTop () { 147function scrollToTop (behavior: 'auto' | 'smooth' = 'auto') {
148 window.scroll(0, 0) 148 window.scrollTo({
149 left: 0,
150 top: 0,
151 behavior
152 })
149} 153}
150 154
151function isInViewport (el: HTMLElement) { 155function isInViewport (el: HTMLElement) {
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html
index a5985a301..88e3d60db 100644
--- a/client/src/app/menu/menu.component.html
+++ b/client/src/app/menu/menu.component.html
@@ -3,7 +3,7 @@
3 <div class="top-menu"> 3 <div class="top-menu">
4 <div *ngIf="isLoggedIn" class="logged-in-block"> 4 <div *ngIf="isLoggedIn" class="logged-in-block">
5 <div> 5 <div>
6 <my-avatar-notification [user]="user" (navigate)="onSameUrlRestoreScrollPosition($event)"></my-avatar-notification> 6 <my-avatar-notification [user]="user" (navigate)="onActiveLinkScrollToAnchor($event)"></my-avatar-notification>
7 7
8 <div class="logged-in-info"> 8 <div class="logged-in-info">
9 <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a> 9 <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a>
@@ -22,7 +22,8 @@
22 22
23 <div class="dropdown-divider"></div> 23 <div class="dropdown-divider"></div>
24 24
25 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/notifications"> 25 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/notifications"
26 #notifications (click)="onActiveLinkScrollToAnchor(notifications)">
26 <my-global-icon iconName="inbox-full" aria-hidden="true"></my-global-icon> <ng-container i18n>My notifications</ng-container> 27 <my-global-icon iconName="inbox-full" aria-hidden="true"></my-global-icon> <ng-container i18n>My notifications</ng-container>
27 </a> 28 </a>
28 29
@@ -35,7 +36,7 @@
35 </a> 36 </a>
36 37
37 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles" 38 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles"
38 #settingsLanguagesSubtitles (click)="onSameUrlRestoreScrollPosition(settingsLanguagesSubtitles)"> 39 #settingsLanguagesSubtitles (click)="onActiveLinkScrollToAnchor(settingsLanguagesSubtitles)">
39 <my-global-icon iconName="video-lang" aria-hidden="true"></my-global-icon> 40 <my-global-icon iconName="video-lang" aria-hidden="true"></my-global-icon>
40 <span i18n>Videos:</span> 41 <span i18n>Videos:</span>
41 <span class="ml-auto text-muted">{{ videoLanguages.join(', ') }}</span> 42 <span class="ml-auto text-muted">{{ videoLanguages.join(', ') }}</span>
@@ -43,7 +44,7 @@
43 44
44 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" 45 <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings"
45 fragment="video-sensitive-content-policy" #settingsSensitiveContentPolicy 46 fragment="video-sensitive-content-policy" #settingsSensitiveContentPolicy
46 (click)="onSameUrlRestoreScrollPosition(settingsSensitiveContentPolicy)"> 47 (click)="onActiveLinkScrollToAnchor(settingsSensitiveContentPolicy)">
47 <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy === 'display' }" iconName="sensitive" aria-hidden="true"></my-global-icon> 48 <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy === 'display' }" iconName="sensitive" aria-hidden="true"></my-global-icon>
48 <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy !== 'display' }" iconName="unsensitive" aria-hidden="true"></my-global-icon> 49 <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy !== 'display' }" iconName="unsensitive" aria-hidden="true"></my-global-icon>
49 <span i18n>Sensitive:</span> 50 <span i18n>Sensitive:</span>
@@ -72,12 +73,12 @@
72 </div> 73 </div>
73 74
74 <div class="logged-in-menu"> 75 <div class="logged-in-menu">
75 <a routerLink="/my-account" routerLinkActive="active" #settingsLink (click)="onSameUrlRestoreScrollPosition(settingsLink)"> 76 <a routerLink="/my-account" routerLinkActive="active" #settingsLink (click)="onActiveLinkScrollToAnchor(settingsLink)">
76 <my-global-icon iconName="user" aria-hidden="true"></my-global-icon> 77 <my-global-icon iconName="user" aria-hidden="true"></my-global-icon>
77 <ng-container i18n>My account</ng-container> 78 <ng-container i18n>My account</ng-container>
78 </a> 79 </a>
79 80
80 <a routerLink="/my-library" routerLinkActive="active" #libraryLink (click)="onSameUrlRestoreScrollPosition(libraryLink)"> 81 <a routerLink="/my-library" routerLinkActive="active" #libraryLink (click)="onActiveLinkScrollToAnchor(libraryLink)">
81 <my-global-icon iconName="channel" aria-hidden="true"></my-global-icon> 82 <my-global-icon iconName="channel" aria-hidden="true"></my-global-icon>
82 <ng-container i18n>My library</ng-container> 83 <ng-container i18n>My library</ng-container>
83 </a> 84 </a>
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts
index 48ed91973..97a3b6d24 100644
--- a/client/src/app/menu/menu.component.ts
+++ b/client/src/app/menu/menu.component.ts
@@ -1,8 +1,10 @@
1import { ViewportScroller } from '@angular/common'
1import { HotkeysService } from 'angular2-hotkeys' 2import { HotkeysService } from 'angular2-hotkeys'
2import * as debug from 'debug' 3import * as debug from 'debug'
3import { switchMap } from 'rxjs/operators' 4import { switchMap } from 'rxjs/operators'
4import { Component, OnInit, ViewChild } from '@angular/core' 5import { Component, OnInit, ViewChild } from '@angular/core'
5import { Router } from '@angular/router' 6import { Router } from '@angular/router'
7import { scrollToTop } from '@app/helpers'
6import { AuthService, AuthStatus, AuthUser, MenuService, RedirectService, ScreenService, ServerService, UserService } from '@app/core' 8import { AuthService, AuthStatus, AuthUser, MenuService, RedirectService, ScreenService, ServerService, UserService } from '@app/core'
7import { LanguageChooserComponent } from '@app/menu/language-chooser.component' 9import { LanguageChooserComponent } from '@app/menu/language-chooser.component'
8import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component' 10import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component'
@@ -39,6 +41,7 @@ export class MenuComponent implements OnInit {
39 } 41 }
40 42
41 constructor ( 43 constructor (
44 private viewportScroller: ViewportScroller,
42 private authService: AuthService, 45 private authService: AuthService,
43 private userService: UserService, 46 private userService: UserService,
44 private serverService: ServerService, 47 private serverService: ServerService,
@@ -199,23 +202,18 @@ export class MenuComponent implements OnInit {
199 return this.languages.find(lang => lang.id === localeId).label 202 return this.languages.find(lang => lang.id === localeId).label
200 } 203 }
201 204
202 onSameUrlRestoreScrollPosition (link: HTMLAnchorElement) { 205 onActiveLinkScrollToAnchor (link: HTMLAnchorElement) {
203 const linkURL = link.getAttribute('href') 206 const linkURL = link.getAttribute('href')
204 const linkHash = link.getAttribute('fragment') 207 const linkHash = link.getAttribute('fragment')
205 208
206 // On same url without fragment restore top scroll position 209 // On same url without fragment restore top scroll position
207 if (!linkHash && this.router.url.includes(linkURL)) { 210 if (!linkHash && this.router.url.includes(linkURL)) {
208 window.scrollTo({ 211 scrollToTop('smooth')
209 left: 0,
210 top: 0,
211 behavior: 'smooth'
212 })
213 } 212 }
214 213
215 // On same url with fragment restore anchor scroll position 214 // On same url with fragment restore anchor scroll position
216 if (linkHash && this.router.url === linkURL) { 215 if (linkHash && this.router.url === linkURL) {
217 const anchor = document.getElementById(link.getAttribute('fragment')) 216 this.viewportScroller.scrollToAnchor(linkHash)
218 anchor.scrollIntoView({ behavior: 'smooth', inline: 'nearest' })
219 } 217 }
220 218
221 if (this.screenService.isInSmallView()) { 219 if (this.screenService.isInSmallView()) {
diff --git a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
index ba5568595..2cafb6c55 100644
--- a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
+++ b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
@@ -3,6 +3,7 @@ import { filter } from 'rxjs/operators'
3import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core' 3import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'
4import { NavigationEnd, Router } from '@angular/router' 4import { NavigationEnd, Router } from '@angular/router'
5import { MenuService, ScreenService } from '@app/core' 5import { MenuService, ScreenService } from '@app/core'
6import { scrollToTop } from '@app/helpers'
6import { GlobalIconName } from '@app/shared/shared-icons' 7import { GlobalIconName } from '@app/shared/shared-icons'
7import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' 8import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap'
8 9
@@ -96,11 +97,7 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
96 97
97 onActiveLinkScrollToTop (link: HTMLAnchorElement) { 98 onActiveLinkScrollToTop (link: HTMLAnchorElement) {
98 if (!this.isBroadcastMessageDisplayed && this.router.url.includes(link.getAttribute('href'))) { 99 if (!this.isBroadcastMessageDisplayed && this.router.url.includes(link.getAttribute('href'))) {
99 window.scrollTo({ 100 scrollToTop('smooth')
100 left: 0,
101 top: 0,
102 behavior: 'smooth'
103 })
104 } 101 }
105 } 102 }
106 103