New UX Part 1.5 (#3105)
This commit is contained in:
parent
c188e0f23b
commit
ac21b04fa4
239 changed files with 1626 additions and 776 deletions
|
|
@ -25,7 +25,7 @@ import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|||
import { SentenceCasePipe } from '../../../_pipes/sentence-case.pipe';
|
||||
import { CircularLoaderComponent } from '../../../shared/circular-loader/circular-loader.component';
|
||||
import { NgClass, NgStyle, AsyncPipe } from '@angular/common';
|
||||
import {TranslocoDirective} from "@ngneat/transloco";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-events-toggle',
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { KEY_CODES } from 'src/app/shared/_services/utility.service';
|
|||
import { SearchResultGroup } from 'src/app/_models/search/search-result-group';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {AsyncPipe, NgClass, NgTemplateOutlet} from '@angular/common';
|
||||
import {TranslocoDirective} from "@ngneat/transloco";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {LoadingComponent} from "../../../shared/loading/loading.component";
|
||||
import {map, startWith, tap} from "rxjs";
|
||||
import {AccountService} from "../../../_services/account.service";
|
||||
|
|
|
|||
|
|
@ -159,40 +159,50 @@
|
|||
}
|
||||
</ul>
|
||||
|
||||
|
||||
@if (!searchFocused) {
|
||||
@if (backToTopNeeded) {
|
||||
<div class="back-to-top">
|
||||
<button class="btn btn-icon scroll-to-top" (click)="scrollToTop()">
|
||||
<i class="fa fa-angle-double-up nav" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{t('scroll-to-top-alt')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
@if((breakpoint$ | async)! > Breakpoint.Tablet) {
|
||||
@if (backToTopNeeded) {
|
||||
<div class="back-to-top">
|
||||
<button class="btn btn-icon scroll-to-top" (click)="scrollToTop()">
|
||||
<i class="fa fa-angle-double-up nav" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{t('scroll-to-top-alt')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if (accountService.currentUser$ | async; as user) {
|
||||
<div class="nav-item">
|
||||
<app-nav-events-toggle [user]="user"></app-nav-events-toggle>
|
||||
</div>
|
||||
<div class="nav-item not-xs-only">
|
||||
<a routerLink="/settings" [fragment]="SettingsTabId.Account" class="dark-exempt btn btn-icon" [title]="t('settings')">
|
||||
<i class="fa fa-cogs nav" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{t('settings')}}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div ngbDropdown class="nav-item dropdown" display="dynamic" placement="bottom-right">
|
||||
<button class="btn btn-outline-secondary primary-text" ngbDropdownToggle>
|
||||
@if((breakpoint$ | async)! <= Breakpoint.Mobile) {
|
||||
<button class="btn btn-outline-secondary primary-text" (click)="openLinkSelectionMenu()">
|
||||
<i class="fa-solid fa-user-circle align-self-center phone-hidden d-xs-inline-block d-sm-inline-block d-md-none"></i>
|
||||
<span class="d-none d-xs-none d-sm-none d-md-inline-block">{{user.username | sentenceCase}}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
<a ngbDropdownItem routerLink="/all-filters/">{{t('all-filters')}}</a>
|
||||
<a ngbDropdownItem routerLink="/announcements/">{{t('announcements')}}</a>
|
||||
<a ngbDropdownItem [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
|
||||
<a ngbDropdownItem (click)="logout()">{{t('logout')}}</a>
|
||||
} @else {
|
||||
<div class="nav-item not-xs-only">
|
||||
<a routerLink="/settings" [fragment]="SettingsTabId.Preferences" class="dark-exempt btn btn-icon" [title]="t('settings')">
|
||||
<i class="fa fa-cogs nav" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{t('settings')}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ngbDropdown class="nav-item dropdown d-sm-none d-md-block" display="dynamic" placement="bottom-right">
|
||||
<button class="btn btn-outline-secondary primary-text" ngbDropdownToggle>
|
||||
<i class="fa-solid fa-user-circle align-self-center phone-hidden d-xs-inline-block d-sm-inline-block d-md-none"></i>
|
||||
<span class="d-none d-xs-none d-sm-none d-md-inline-block">{{user.username | sentenceCase}}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
<a ngbDropdownItem routerLink="/all-filters/">{{t('all-filters')}}</a>
|
||||
<a ngbDropdownItem routerLink="/announcements/">{{t('announcements')}}</a>
|
||||
<a ngbDropdownItem [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
|
||||
<a ngbDropdownItem (click)="logout()">{{t('logout')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import {AsyncPipe, DOCUMENT, NgIf, NgOptimizedImage} from '@angular/common';
|
||||
import {AsyncPipe, DOCUMENT, NgOptimizedImage, NgTemplateOutlet} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
ElementRef,
|
||||
ElementRef, HostListener,
|
||||
inject,
|
||||
Inject,
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import {NavigationEnd, Router, RouterLink, RouterLinkActive} from '@angular/router';
|
||||
import {fromEvent} from 'rxjs';
|
||||
import {BehaviorSubject, fromEvent, Observable} from 'rxjs';
|
||||
import {debounceTime, distinctUntilChanged, filter, tap} from 'rxjs/operators';
|
||||
import {Chapter} from 'src/app/_models/chapter';
|
||||
import {UserCollection} from 'src/app/_models/collection-tag';
|
||||
|
|
@ -29,12 +29,12 @@ import {SearchService} from 'src/app/_services/search.service';
|
|||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {SentenceCasePipe} from '../../../_pipes/sentence-case.pipe';
|
||||
import {PersonRolePipe} from '../../../_pipes/person-role.pipe';
|
||||
import {NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {EventsWidgetComponent} from '../events-widget/events-widget.component';
|
||||
import {SeriesFormatComponent} from '../../../shared/series-format/series-format.component';
|
||||
import {ImageComponent} from '../../../shared/image/image.component';
|
||||
import {GroupedTypeaheadComponent, SearchEvent} from '../grouped-typeahead/grouped-typeahead.component';
|
||||
import {TranslocoDirective} from "@ngneat/transloco";
|
||||
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
||||
import {FilterUtilitiesService} from "../../../shared/_services/filter-utilities.service";
|
||||
import {FilterStatement} from "../../../_models/metadata/v2/filter-statement";
|
||||
import {FilterField} from "../../../_models/metadata/v2/filter-field";
|
||||
|
|
@ -48,6 +48,10 @@ import {PromotedIconComponent} from "../../../shared/_components/promoted-icon/p
|
|||
import {SettingsTabId} from "../../../sidenav/preference-nav/preference-nav.component";
|
||||
import {Breakpoint, UtilityService} from "../../../shared/_services/utility.service";
|
||||
import {WikiLink} from "../../../_models/wiki";
|
||||
import {
|
||||
GenericListModalComponent
|
||||
} from "../../../statistics/_components/_modals/generic-list-modal/generic-list-modal.component";
|
||||
import {NavLinkModalComponent} from "../nav-link-modal/nav-link-modal.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-header',
|
||||
|
|
@ -57,7 +61,7 @@ import {WikiLink} from "../../../_models/wiki";
|
|||
standalone: true,
|
||||
imports: [RouterLink, RouterLinkActive, NgOptimizedImage, GroupedTypeaheadComponent, ImageComponent,
|
||||
SeriesFormatComponent, EventsWidgetComponent, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem,
|
||||
AsyncPipe, PersonRolePipe, SentenceCasePipe, TranslocoDirective, ProviderImagePipe, ProviderNamePipe, CollectionOwnerComponent, PromotedIconComponent]
|
||||
AsyncPipe, PersonRolePipe, SentenceCasePipe, TranslocoDirective, ProviderImagePipe, ProviderNamePipe, CollectionOwnerComponent, PromotedIconComponent, NgTemplateOutlet]
|
||||
})
|
||||
export class NavHeaderComponent implements OnInit {
|
||||
|
||||
|
|
@ -71,6 +75,7 @@ export class NavHeaderComponent implements OnInit {
|
|||
protected readonly navService = inject(NavService);
|
||||
protected readonly imageService = inject(ImageService);
|
||||
protected readonly utilityService = inject(UtilityService);
|
||||
protected readonly modalService = inject(NgbModal);
|
||||
|
||||
protected readonly FilterField = FilterField;
|
||||
protected readonly WikiLink = WikiLink;
|
||||
|
|
@ -90,6 +95,15 @@ export class NavHeaderComponent implements OnInit {
|
|||
searchFocused: boolean = false;
|
||||
scrollElem: HTMLElement;
|
||||
|
||||
breakpointSource = new BehaviorSubject<Breakpoint>(this.utilityService.getActiveBreakpoint());
|
||||
breakpoint$: Observable<Breakpoint> = this.breakpointSource.asObservable();
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
@HostListener('window:orientationchange', ['$event'])
|
||||
onResize(){
|
||||
this.breakpointSource.next(this.utilityService.getActiveBreakpoint());
|
||||
}
|
||||
|
||||
constructor(@Inject(DOCUMENT) private document: Document) {
|
||||
this.scrollElem = this.document.body;
|
||||
}
|
||||
|
|
@ -134,10 +148,6 @@ export class NavHeaderComponent implements OnInit {
|
|||
this.document.getElementById('content')?.focus();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
onChangeSearch(evt: SearchEvent) {
|
||||
this.isLoading = true;
|
||||
this.searchTerm = evt.value.trim();
|
||||
|
|
@ -290,4 +300,9 @@ export class NavHeaderComponent implements OnInit {
|
|||
this.navService.toggleSideNav();
|
||||
}
|
||||
|
||||
openLinkSelectionMenu() {
|
||||
const ref = this.modalService.open(NavLinkModalComponent, {fullscreen: 'sm'});
|
||||
ref.componentInstance.logoutFn = this.logout.bind(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
|
||||
<ng-container *transloco="let t; read:'nav-header'">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{t('nav-link-header')}}</h4>
|
||||
<button type="button" class="btn-close" [attr.aria-label]="t('close')" (click)="close()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<a routerLink="/settings" [fragment]="SettingsTabId.Preferences" [title]="t('settings')">{{t('settings')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a routerLink="/all-filters/">{{t('all-filters')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a routerLink="/announcements/">{{t('announcements')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a [href]="WikiLink.Guides" rel="noopener noreferrer" target="_blank">{{t('help')}}</a>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<a href="javascript:void(0);" (click)="logout()">{{t('logout')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" (click)="close()">{{t('close')}}</button>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import {Component, inject, Input} from '@angular/core';
|
||||
import {WikiLink} from "../../../_models/wiki";
|
||||
import {NgbActiveModal, NgbDropdownItem} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {RouterLink} from "@angular/router";
|
||||
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
||||
import {ReactiveFormsModule} from "@angular/forms";
|
||||
import {Select2Module} from "ng-select2-component";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {SettingsTabId} from "../../../sidenav/preference-nav/preference-nav.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-link-modal',
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgbDropdownItem,
|
||||
RouterLink,
|
||||
FilterPipe,
|
||||
ReactiveFormsModule,
|
||||
Select2Module,
|
||||
TranslocoDirective
|
||||
],
|
||||
templateUrl: './nav-link-modal.component.html',
|
||||
styleUrl: './nav-link-modal.component.scss'
|
||||
})
|
||||
export class NavLinkModalComponent {
|
||||
|
||||
@Input({required: true}) logoutFn!: () => void;
|
||||
|
||||
private readonly modal = inject(NgbActiveModal);
|
||||
|
||||
protected readonly WikiLink = WikiLink;
|
||||
|
||||
close() {
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.logoutFn();
|
||||
}
|
||||
|
||||
protected readonly SettingsTabId = SettingsTabId;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue