From ddb83e49ece4e76df1af98aeea30c1d8d133f48c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 5 Dec 2018 14:21:10 +0100 Subject: [PATCH] My account menu -> open entries on hover --- .../app/+my-account/my-account.component.html | 37 +------ .../app/+my-account/my-account.component.scss | 15 +-- .../app/+my-account/my-account.component.ts | 97 +++++++++++-------- .../menu/top-menu-dropdown.component.html | 18 ++++ .../menu/top-menu-dropdown.component.scss | 14 +++ .../menu/top-menu-dropdown.component.ts | 75 ++++++++++++++ client/src/app/shared/shared.module.ts | 5 +- 7 files changed, 168 insertions(+), 93 deletions(-) create mode 100644 client/src/app/shared/menu/top-menu-dropdown.component.html create mode 100644 client/src/app/shared/menu/top-menu-dropdown.component.scss create mode 100644 client/src/app/shared/menu/top-menu-dropdown.component.ts diff --git a/client/src/app/+my-account/my-account.component.html b/client/src/app/+my-account/my-account.component.html index 41333c25a..3999252be 100644 --- a/client/src/app/+my-account/my-account.component.html +++ b/client/src/app/+my-account/my-account.component.html @@ -1,40 +1,5 @@
- +
diff --git a/client/src/app/+my-account/my-account.component.scss b/client/src/app/+my-account/my-account.component.scss index 6243c6dcf..4f111efdf 100644 --- a/client/src/app/+my-account/my-account.component.scss +++ b/client/src/app/+my-account/my-account.component.scss @@ -1,14 +1,3 @@ -.my-library, .misc { - span[role=button] { - cursor: pointer; - } - - a { - display: block; - } +.row { + flex-direction: column; } - -/deep/ .dropdown-toggle::after { - position: relative; - top: 2px; -} \ No newline at end of file diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts index d728caf07..d9381ebfa 100644 --- a/client/src/app/+my-account/my-account.component.ts +++ b/client/src/app/+my-account/my-account.component.ts @@ -1,38 +1,72 @@ -import { Component, OnDestroy, OnInit } from '@angular/core' +import { Component } from '@angular/core' import { ServerService } from '@app/core' -import { NavigationStart, Router } from '@angular/router' -import { filter } from 'rxjs/operators' import { I18n } from '@ngx-translate/i18n-polyfill' -import { Subscription } from 'rxjs' +import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component' @Component({ selector: 'my-my-account', templateUrl: './my-account.component.html', styleUrls: [ './my-account.component.scss' ] }) -export class MyAccountComponent implements OnInit, OnDestroy { - - libraryLabel = '' - miscLabel = '' - - private routeSub: Subscription +export class MyAccountComponent { + menuEntries: TopMenuDropdownParam[] = [] constructor ( private serverService: ServerService, - private router: Router, private i18n: I18n - ) {} + ) { - ngOnInit () { - this.updateLabels(this.router.url) + const libraryEntries: TopMenuDropdownParam = { + label: this.i18n('My library'), + children: [ + { + label: this.i18n('My channels'), + routerLink: '/my-account/videos' + }, + { + label: this.i18n('My videos'), + routerLink: '/my-account/videos' + }, + { + label: this.i18n('My subscriptions'), + routerLink: '/my-account/subscriptions' + } + ] + } - this.routeSub = this.router.events - .pipe(filter(event => event instanceof NavigationStart)) - .subscribe((event: NavigationStart) => this.updateLabels(event.url)) - } + if (this.isVideoImportEnabled()) { + libraryEntries.children.push({ + label: 'My imports', + routerLink: '/my-account/video-imports' + }) + } - ngOnDestroy () { - if (this.routeSub) this.routeSub.unsubscribe() + const miscEntries: TopMenuDropdownParam = { + label: this.i18n('Misc'), + children: [ + { + label: this.i18n('Muted accounts'), + routerLink: '/my-account/blocklist/accounts' + }, + { + label: this.i18n('Muted instances'), + routerLink: '/my-account/blocklist/servers' + }, + { + label: this.i18n('Ownership changes'), + routerLink: '/my-account/ownership' + } + ] + } + + this.menuEntries = [ + { + label: this.i18n('My settings'), + routerLink: '/my-account/settings' + }, + libraryEntries, + miscEntries + ] } isVideoImportEnabled () { @@ -41,27 +75,4 @@ export class MyAccountComponent implements OnInit, OnDestroy { return importConfig.http.enabled || importConfig.torrent.enabled } - private updateLabels (url: string) { - const [ path ] = url.split('?') - - if (path.startsWith('/my-account/video-channels')) { - this.libraryLabel = this.i18n('Channels') - } else if (path.startsWith('/my-account/videos')) { - this.libraryLabel = this.i18n('Videos') - } else if (path.startsWith('/my-account/subscriptions')) { - this.libraryLabel = this.i18n('Subscriptions') - } else if (path.startsWith('/my-account/video-imports')) { - this.libraryLabel = this.i18n('Video imports') - } else { - this.libraryLabel = '' - } - - if (path.startsWith('/my-account/blocklist/accounts')) { - this.miscLabel = this.i18n('Muted accounts') - } else if (path.startsWith('/my-account/blocklist/servers')) { - this.miscLabel = this.i18n('Muted instances') - } else { - this.miscLabel = '' - } - } } 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 @@ + 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 @@ +.parent-entry { + span[role=button] { + cursor: pointer; + } + + a { + display: block; + } +} + +/deep/ .dropdown-toggle::after { + position: relative; + top: 2px; +} 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 @@ +import { Component, Input, OnDestroy, OnInit } from '@angular/core' +import { filter, take } from 'rxjs/operators' +import { NavigationStart, Router } from '@angular/router' +import { Subscription } from 'rxjs' +import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' +import { drop } from 'lodash-es' + +export type TopMenuDropdownParam = { + label: string + routerLink?: string + + children?: { + label: string + routerLink: string + }[] +} + +@Component({ + selector: 'my-top-menu-dropdown', + templateUrl: './top-menu-dropdown.component.html', + styleUrls: [ './top-menu-dropdown.component.scss' ] +}) +export class TopMenuDropdownComponent implements OnInit, OnDestroy { + @Input() menuEntries: TopMenuDropdownParam[] = [] + + suffixLabels: { [ parentLabel: string ]: string } + + private openedOnHover = false + private routeSub: Subscription + + constructor (private router: Router) {} + + ngOnInit () { + this.updateChildLabels(window.location.pathname) + + this.routeSub = this.router.events + .pipe(filter(event => event instanceof NavigationStart)) + .subscribe(() => this.updateChildLabels(window.location.pathname)) + } + + ngOnDestroy () { + if (this.routeSub) this.routeSub.unsubscribe() + } + + openDropdownOnHover (dropdown: NgbDropdown) { + this.openedOnHover = true + dropdown.open() + + // Menu was closed + dropdown.openChange + .pipe(take(1)) + .subscribe(e => this.openedOnHover = false) + } + + closeDropdownIfHovered (dropdown: NgbDropdown) { + if (this.openedOnHover === false) return + + dropdown.close() + this.openedOnHover = false + } + + private updateChildLabels (path: string) { + this.suffixLabels = {} + + for (const entry of this.menuEntries) { + if (!entry.children) continue + + for (const child of entry.children) { + if (path.startsWith(child.routerLink)) { + this.suffixLabels[entry.label] = child.label + } + } + } + } +} 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' import { UserBanModalComponent } from '@app/shared/moderation' import { UserModerationDropdownComponent } from '@app/shared/moderation/user-moderation-dropdown.component' import { BlocklistService } from '@app/shared/blocklist' +import { TopMenuDropdownComponent } from '@app/shared/menu/top-menu-dropdown.component' @NgModule({ imports: [ @@ -102,7 +103,8 @@ import { BlocklistService } from '@app/shared/blocklist' RemoteSubscribeComponent, InstanceFeaturesTableComponent, UserBanModalComponent, - UserModerationDropdownComponent + UserModerationDropdownComponent, + TopMenuDropdownComponent ], exports: [ @@ -141,6 +143,7 @@ import { BlocklistService } from '@app/shared/blocklist' InstanceFeaturesTableComponent, UserBanModalComponent, UserModerationDropdownComponent, + TopMenuDropdownComponent, NumberFormatterPipe, ObjectLengthPipe,