Merge pull request #4806 from tsiegleauq/smarter--back-button
Smarter back button
This commit is contained in:
commit
ae618fce20
@ -17,6 +17,7 @@ import { PingService } from './core/core-services/ping.service';
|
|||||||
import { SpinnerService } from './core/ui-services/spinner.service';
|
import { SpinnerService } from './core/ui-services/spinner.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ViewUser } from './site/users/models/view-user';
|
import { ViewUser } from './site/users/models/view-user';
|
||||||
|
import { RoutingStateService } from './core/ui-services/routing-state.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enhance array with own functions
|
* Enhance array with own functions
|
||||||
@ -80,7 +81,8 @@ export class AppComponent {
|
|||||||
loadFontService: LoadFontService,
|
loadFontService: LoadFontService,
|
||||||
dataStoreUpgradeService: DataStoreUpgradeService, // to start it.
|
dataStoreUpgradeService: DataStoreUpgradeService, // to start it.
|
||||||
prioritizeService: PrioritizeService,
|
prioritizeService: PrioritizeService,
|
||||||
pingService: PingService
|
pingService: PingService,
|
||||||
|
routingState: RoutingStateService
|
||||||
) {
|
) {
|
||||||
// manually add the supported languages
|
// manually add the supported languages
|
||||||
translate.addLangs(['en', 'de', 'cs']);
|
translate.addLangs(['en', 'de', 'cs']);
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RoutingStateService } from './routing-state.service';
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
|
describe('RoutingStateService', () => {
|
||||||
|
beforeEach(() =>
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: RoutingStateService = TestBed.get(RoutingStateService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
51
client/src/app/core/ui-services/routing-state.service.ts
Normal file
51
client/src/app/core/ui-services/routing-state.service.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router, RoutesRecognized } from '@angular/router';
|
||||||
|
import { filter, pairwise } from 'rxjs/operators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watches URL changes.
|
||||||
|
* Can be enhanced using locale storage to support back-navigation even after reload
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class RoutingStateService {
|
||||||
|
/**
|
||||||
|
* Hold the previous URL
|
||||||
|
*/
|
||||||
|
private _previousUrl: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsafe paths that the user should not go "back" to
|
||||||
|
* TODO: Might also work using Routing parameters
|
||||||
|
*/
|
||||||
|
private unsafeUrls: string[] = ['/login', '/privacypolicy', '/legalnotice'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Get the previous URL
|
||||||
|
*/
|
||||||
|
public get previousUrl(): string {
|
||||||
|
return this._previousUrl ? this._previousUrl : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isSafePrevUrl(): boolean {
|
||||||
|
return !!this.previousUrl && !this.unsafeUrls.includes(this.previousUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch routing changes and save the last visited URL
|
||||||
|
*
|
||||||
|
* @param router Angular Router
|
||||||
|
*/
|
||||||
|
public constructor(private router: Router) {
|
||||||
|
this.router.events
|
||||||
|
.pipe(
|
||||||
|
filter(e => e instanceof RoutesRecognized),
|
||||||
|
pairwise()
|
||||||
|
)
|
||||||
|
.subscribe((event: any[]) => {
|
||||||
|
this._previousUrl = event[0].urlAfterRedirects;
|
||||||
|
console.log('prev URL: ', this._previousUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,12 @@
|
|||||||
<mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" class="sticky-toolbar">
|
<mat-toolbar color="primary" [ngClass]="multiSelectMode ? 'multi-select' : ''" class="sticky-toolbar">
|
||||||
<div class="toolbar-left">
|
<div class="toolbar-left">
|
||||||
<!-- Nav menu -->
|
<!-- Nav menu -->
|
||||||
<button mat-icon-button *ngIf="vp.isMobile && nav && !multiSelectMode" (click)="clickHamburgerMenu()">
|
<button mat-icon-button *ngIf="vp.isMobile && !showBackButton" (click)="clickHamburgerMenu()">
|
||||||
<mat-icon>menu</mat-icon>
|
<mat-icon>menu</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Exit / Back button -->
|
<!-- Exit / Back button -->
|
||||||
<button mat-icon-button *ngIf="!nav && !editMode && !multiSelectMode" (click)="onBackButton()">
|
<button mat-icon-button *ngIf="showBackButton" (click)="onBackButton()">
|
||||||
<mat-icon>arrow_back</mat-icon>
|
<mat-icon>arrow_back</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
||||||
import { MainMenuService } from 'app/core/core-services/main-menu.service';
|
import { MainMenuService } from 'app/core/core-services/main-menu.service';
|
||||||
|
import { RoutingStateService } from 'app/core/ui-services/routing-state.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reusable head bar component for Apps.
|
* Reusable head bar component for Apps.
|
||||||
@ -111,6 +111,10 @@ export class HeadBarComponent {
|
|||||||
@Output()
|
@Output()
|
||||||
public saveEvent = new EventEmitter<boolean>();
|
public saveEvent = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
public get showBackButton(): boolean {
|
||||||
|
return !this.nav && !this.editMode && !this.multiSelectMode && this.routingState.isSafePrevUrl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty constructor
|
* Empty constructor
|
||||||
*/
|
*/
|
||||||
@ -119,7 +123,7 @@ export class HeadBarComponent {
|
|||||||
private menu: MainMenuService,
|
private menu: MainMenuService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private location: Location
|
private routingState: RoutingStateService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +153,7 @@ export class HeadBarComponent {
|
|||||||
*/
|
*/
|
||||||
public onBackButton(): void {
|
public onBackButton(): void {
|
||||||
if (this.goBack) {
|
if (this.goBack) {
|
||||||
this.location.back();
|
this.router.navigateByUrl(this.routingState.previousUrl);
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate([this.prevUrl], { relativeTo: this.route });
|
this.router.navigate([this.prevUrl], { relativeTo: this.route });
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ bleach>=1.5.0,<3.2
|
|||||||
channels>=2.1.2,<2.2
|
channels>=2.1.2,<2.2
|
||||||
daphne>=2.2,<2.3
|
daphne>=2.2,<2.3
|
||||||
Django>=2.1,<2.3
|
Django>=2.1,<2.3
|
||||||
djangorestframework>=3.4,<3.10
|
djangorestframework>=3.9.4,<3.10
|
||||||
jsonfield2>=3.0,<3.1
|
jsonfield2>=3.0,<3.1
|
||||||
jsonschema>=3.0,<3.1
|
jsonschema>=3.0,<3.1
|
||||||
lz4>=2.1.6
|
lz4>=2.1.6
|
||||||
|
Loading…
Reference in New Issue
Block a user