aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/menu/top-menu-dropdown.component.html18
-rw-r--r--client/src/app/shared/menu/top-menu-dropdown.component.scss14
-rw-r--r--client/src/app/shared/menu/top-menu-dropdown.component.ts75
-rw-r--r--client/src/app/shared/shared.module.ts5
4 files changed, 111 insertions, 1 deletions
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.html b/client/src/app/shared/menu/top-menu-dropdown.component.html
new file mode 100644
index 000000000..2d6d1c4bf
--- /dev/null
+++ b/client/src/app/shared/menu/top-menu-dropdown.component.html
@@ -0,0 +1,18 @@
1<div class="sub-menu">
2 <ng-container *ngFor="let menuEntry of menuEntries">
3
4 <a *ngIf="menuEntry.routerLink" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page">{{ menuEntry.label }}</a>
5
6 <div *ngIf="!menuEntry.routerLink" ngbDropdown class="parent-entry" #dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)">
7 <span (mouseenter)="openDropdownOnHover(dropdown)" role="button" class="title-page" [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownToggle>
8 <ng-container i18n>{{ menuEntry.label }}</ng-container>
9 <ng-container *ngIf="!!suffixLabels[menuEntry.label]"> - {{ suffixLabels[menuEntry.label] }}</ng-container>
10 </span>
11
12 <div ngbDropdownMenu>
13 <a *ngFor="let menuChild of menuEntry.children" class="dropdown-item" [routerLink]="menuChild.routerLink">{{ menuChild.label }}</a>
14 </div>
15 </div>
16
17 </ng-container>
18</div>
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.scss b/client/src/app/shared/menu/top-menu-dropdown.component.scss
new file mode 100644
index 000000000..f3ef8f814
--- /dev/null
+++ b/client/src/app/shared/menu/top-menu-dropdown.component.scss
@@ -0,0 +1,14 @@
1.parent-entry {
2 span[role=button] {
3 cursor: pointer;
4 }
5
6 a {
7 display: block;
8 }
9}
10
11/deep/ .dropdown-toggle::after {
12 position: relative;
13 top: 2px;
14}
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.ts b/client/src/app/shared/menu/top-menu-dropdown.component.ts
new file mode 100644
index 000000000..272b721b2
--- /dev/null
+++ b/client/src/app/shared/menu/top-menu-dropdown.component.ts
@@ -0,0 +1,75 @@
1import { Component, Input, OnDestroy, OnInit } from '@angular/core'
2import { filter, take } from 'rxjs/operators'
3import { NavigationStart, Router } from '@angular/router'
4import { Subscription } from 'rxjs'
5import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
6import { drop } from 'lodash-es'
7
8export type TopMenuDropdownParam = {
9 label: string
10 routerLink?: string
11
12 children?: {
13 label: string
14 routerLink: string
15 }[]
16}
17
18@Component({
19 selector: 'my-top-menu-dropdown',
20 templateUrl: './top-menu-dropdown.component.html',
21 styleUrls: [ './top-menu-dropdown.component.scss' ]
22})
23export class TopMenuDropdownComponent implements OnInit, OnDestroy {
24 @Input() menuEntries: TopMenuDropdownParam[] = []
25
26 suffixLabels: { [ parentLabel: string ]: string }
27
28 private openedOnHover = false
29 private routeSub: Subscription
30
31 constructor (private router: Router) {}
32
33 ngOnInit () {
34 this.updateChildLabels(window.location.pathname)
35
36 this.routeSub = this.router.events
37 .pipe(filter(event => event instanceof NavigationStart))
38 .subscribe(() => this.updateChildLabels(window.location.pathname))
39 }
40
41 ngOnDestroy () {
42 if (this.routeSub) this.routeSub.unsubscribe()
43 }
44
45 openDropdownOnHover (dropdown: NgbDropdown) {
46 this.openedOnHover = true
47 dropdown.open()
48
49 // Menu was closed
50 dropdown.openChange
51 .pipe(take(1))
52 .subscribe(e => this.openedOnHover = false)
53 }
54
55 closeDropdownIfHovered (dropdown: NgbDropdown) {
56 if (this.openedOnHover === false) return
57
58 dropdown.close()
59 this.openedOnHover = false
60 }
61
62 private updateChildLabels (path: string) {
63 this.suffixLabels = {}
64
65 for (const entry of this.menuEntries) {
66 if (!entry.children) continue
67
68 for (const child of entry.children) {
69 if (path.startsWith(child.routerLink)) {
70 this.suffixLabels[entry.label] = child.label
71 }
72 }
73 }
74 }
75}
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index a2fa27b72..9810e9485 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -61,6 +61,7 @@ import { OverviewService } from '@app/shared/overview'
61import { UserBanModalComponent } from '@app/shared/moderation' 61import { UserBanModalComponent } from '@app/shared/moderation'
62import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component' 62import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component'
63import { BlocklistService } from '@app/shared/blocklist' 63import { BlocklistService } from '@app/shared/blocklist'
64import { TopMenuDropdownComponent } from '@app/shared/menu/top-menu-dropdown.component'
64 65
65@NgModule({ 66@NgModule({
66 imports: [ 67 imports: [
@@ -102,7 +103,8 @@ import { BlocklistService } from '@app/shared/blocklist'
102 RemoteSubscribeComponent, 103 RemoteSubscribeComponent,
103 InstanceFeaturesTableComponent, 104 InstanceFeaturesTableComponent,
104 UserBanModalComponent, 105 UserBanModalComponent,
105 UserModerationDropdownComponent 106 UserModerationDropdownComponent,
107 TopMenuDropdownComponent
106 ], 108 ],
107 109
108 exports: [ 110 exports: [
@@ -141,6 +143,7 @@ import { BlocklistService } from '@app/shared/blocklist'
141 InstanceFeaturesTableComponent, 143 InstanceFeaturesTableComponent,
142 UserBanModalComponent, 144 UserBanModalComponent,
143 UserModerationDropdownComponent, 145 UserModerationDropdownComponent,
146 TopMenuDropdownComponent,
144 147
145 NumberFormatterPipe, 148 NumberFormatterPipe,
146 ObjectLengthPipe, 149 ObjectLengthPipe,