Skip to content

Commit

Permalink
Merge pull request #510 from appuio/back
Browse files Browse the repository at this point in the history
Navigate back via history
  • Loading branch information
ccremer authored Mar 16, 2023
2 parents 0becf45 + 46c70c6 commit d89d9ce
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 16 deletions.
4 changes: 3 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { OrganizationCollectionService } from './store/organization-collection.s
import { KubernetesDataServiceFactory } from './store/kubernetes-data.service';
import { KubernetesCollectionServiceFactory } from './store/kubernetes-collection.service';
import { SelfSubjectAccessReviewCollectionService } from './store/ssar-collection.service';
import { NavigationService } from './shared/navigation.service';

@NgModule({
declarations: [
Expand Down Expand Up @@ -72,7 +73,8 @@ import { SelfSubjectAccessReviewCollectionService } from './store/ssar-collectio
SelfSubjectAccessReviewCollectionService,
{
provide: APP_INITIALIZER,
deps: [AppConfigService, OAuthService],
// start the NavigationService early to catch route events.
deps: [AppConfigService, OAuthService, NavigationService],
useFactory: initializeAppFactory,
multi: true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{{ payload.billingEntity.metadata.name }}
<span i18n>Members</span>
</div>
<a [routerLink]="['../..']" class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<a appBackLink="../.." class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<fa-icon [icon]="faClose"></fa-icon>
</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { defaultIfNotFound } from '../../store/kubernetes-collection.service';
import { ClusterRoleCollectionService } from '../../store/cluster-role-collection.service';
import { ClusterRole } from '../../types/clusterRole';
import { KubeObject } from '../../types/entity';
import { NavigationService } from '../../shared/navigation.service';

interface Payload {
billingEntity: BillingEntity;
Expand Down Expand Up @@ -54,6 +55,7 @@ export class BillingentityMembersComponent implements OnInit, OnDestroy {
constructor(
private route: ActivatedRoute,
private router: Router,
private navigationService: NavigationService,
private billingService: BillingEntityCollectionService,
private roleService: ClusterRoleCollectionService,
public rolebindingService: ClusterRolebindingCollectionService,
Expand Down Expand Up @@ -234,7 +236,7 @@ export class BillingentityMembersComponent implements OnInit, OnDestroy {
severity: 'success',
summary: $localize`Successfully saved`,
});
void this.router.navigate(['../..'], { relativeTo: this.route });
void this.router.navigate([this.navigationService.previousLocation()], { relativeTo: this.route });
},
error: (error) => {
this.messageService.add({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="surface-card p-4 shadow-2 border-round mb-4">
<div class="flex flex-row justify-content-between">
<div class="text-3xl font-medium text-900 mb-3">{{ billingEntity.metadata.name }}</div>
<a [routerLink]="['..']" class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<a appBackLink=".." class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<fa-icon [icon]="faClose"></fa-icon>
</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{{ payload.organization.metadata.name }}
</ng-template>
</div>
<a [routerLink]="['..']" class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<a appBackLink=".." class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<fa-icon [icon]="faClose"></fa-icon>
</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MessageService } from 'primeng/api';
import { OrganizationNameService } from '../organization-name.service';
import { OrganizationCollectionService } from '../../store/organization-collection.service';
import { BillingEntity } from '../../types/billing-entity';
import { NavigationService } from '../../shared/navigation.service';

@Component({
selector: 'app-organization-form',
Expand Down Expand Up @@ -40,7 +41,8 @@ export class OrganizationFormComponent implements OnInit, OnDestroy {
private activatedRoute: ActivatedRoute,
private messageService: MessageService,
private organizationNameService: OrganizationNameService,
public organizationCollectionService: OrganizationCollectionService
public organizationCollectionService: OrganizationCollectionService,
private navigationService: NavigationService
) {}

ngOnInit(): void {
Expand Down Expand Up @@ -114,12 +116,11 @@ export class OrganizationFormComponent implements OnInit, OnDestroy {
severity: 'success',
summary: $localize`Successfully saved`,
});
void this.router.navigate(['..'], { relativeTo: this.activatedRoute });
void this.router.navigate([this.navigationService.previousLocation()], { relativeTo: this.activatedRoute });
}

private saveOrUpdateFailure(err: Error): void {
let detail = '';
console.debug('error!', err);
if ('message' in err) {
detail = err.message;
}
Expand All @@ -132,6 +133,7 @@ export class OrganizationFormComponent implements OnInit, OnDestroy {
this.messageService.add({
severity: 'error',
summary: $localize`Error`,
sticky: true,
detail,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{{ payload.members.metadata.namespace }}
<span i18n>Members</span>
</div>
<a [routerLink]="['../..']" class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<a appBackLink="../.." class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<fa-icon [icon]="faClose"></fa-icon>
</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MessageService } from 'primeng/api';
import { RoleBinding } from 'src/app/types/role-binding';
import { OrganizationMembersCollectionService } from '../../store/organizationmembers-collection.service';
import { RolebindingCollectionService } from '../../store/rolebinding-collection.service';
import { NavigationService } from '../../shared/navigation.service';

interface Payload {
members: OrganizationMembers;
Expand Down Expand Up @@ -47,7 +48,8 @@ export class OrganizationMembersEditComponent implements OnInit {
private messageService: MessageService,
private router: Router,
private membersService: OrganizationMembersCollectionService,
private rolebindingService: RolebindingCollectionService
private rolebindingService: RolebindingCollectionService,
private navigationService: NavigationService
) {}

get userRefs(): FormArray | undefined {
Expand Down Expand Up @@ -165,7 +167,7 @@ export class OrganizationMembersEditComponent implements OnInit {
severity: 'success',
summary: $localize`Successfully saved`,
});
void this.router.navigate(['../..'], { relativeTo: this.activatedRoute });
void this.router.navigate([this.navigationService.previousLocation()], { relativeTo: this.activatedRoute });
},
error: (error) => {
this.messageService.add({
Expand Down
23 changes: 23 additions & 0 deletions src/app/shared/back-link.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Directive, HostListener, Input } from '@angular/core';
import { NavigationService } from './navigation.service';
import { ActivatedRoute, Router } from '@angular/router';

/**
* This directive adds a `click` event listener to navigate back in history.
* It accepts an input that is used as the default path in case there is no history (e.g. opened link in a new tab).
*/
@Directive({
selector: '[appBackLink]',
})
export class BackLinkDirective {
constructor(private navigation: NavigationService, private router: Router, private activatedRoute: ActivatedRoute) {}

@Input()
appBackLink?: string;

@HostListener('click')
onClick(): void {
const route = this.navigation.previousLocation(this.appBackLink);
void this.router.navigate([route], { relativeTo: this.activatedRoute });
}
}
35 changes: 35 additions & 0 deletions src/app/shared/navigation.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';

/**
* Inspired by https://nils-mehlhorn.de/posts/angular-navigate-back-previous-page/
* Modified to be used with a Router working with default and relative paths in case the history is empty.
*/
@Injectable({ providedIn: 'root' })
export class NavigationService {
private history: string[] = [];

constructor(private router: Router) {
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
this.history.push(event.urlAfterRedirects);
this.history.splice(0, this.history.length - 5); // only keep the latest few, no need for more.
}
});
}

/**
* Gets the previous URI location in the history.
* @param defaultPath if the history is empty, return this path as fallback value
* @returns the URI, or '/' if no default was given.
*/
previousLocation(defaultPath?: string): string {
void this.history.pop(); // remove "current" location
if (this.history.length > 0) {
const previousLocation = this.history.pop();
return previousLocation ?? defaultPath ?? '/';
} else {
return defaultPath ?? '/';
}
}
}
4 changes: 3 additions & 1 deletion src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import { MessageModule } from 'primeng/message';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { MultiSelectModule } from 'primeng/multiselect';
import { ProgressSpinnerModule } from 'primeng/progressspinner';
import { BackLinkDirective } from './back-link.directive';

@NgModule({
declarations: [],
declarations: [BackLinkDirective],
imports: [],
exports: [
CommonModule,
Expand All @@ -47,6 +48,7 @@ import { ProgressSpinnerModule } from 'primeng/progressspinner';
ConfirmDialogModule,
MultiSelectModule,
ProgressSpinnerModule,
BackLinkDirective,
],
})
export class SharedModule {}
2 changes: 1 addition & 1 deletion src/app/teams/team-edit/team-edit.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{{ team.metadata.name }}
</ng-template>
</div>
<a [routerLink]="['../..']" class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<a appBackLink="../.." class="text-blue-500 hover:text-primary text-2xl cursor-pointer">
<fa-icon [icon]="faClose"></fa-icon>
</a>
</div>
Expand Down
6 changes: 4 additions & 2 deletions src/app/teams/team-edit/team-edit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@ang
import { MessageService } from 'primeng/api';
import { Observable, of, take, tap } from 'rxjs';
import { TeamCollectionService } from '../../store/team-collection.service';
import { NavigationService } from '../../shared/navigation.service';

@Component({
selector: 'app-team-edit',
Expand All @@ -26,7 +27,8 @@ export class TeamEditComponent implements OnInit {
private router: Router,
private activatedRoute: ActivatedRoute,
private messageService: MessageService,
public teamService: TeamCollectionService
public teamService: TeamCollectionService,
private navigationService: NavigationService
) {}

get userRefs(): FormArray {
Expand Down Expand Up @@ -71,7 +73,7 @@ export class TeamEditComponent implements OnInit {
severity: 'success',
summary: $localize`Successfully saved`,
});
void this.router.navigate(['../..'], { relativeTo: this.activatedRoute });
void this.router.navigate([this.navigationService.previousLocation()], { relativeTo: this.activatedRoute });
},
error: (error) => {
let detail = '';
Expand Down
2 changes: 1 addition & 1 deletion src/app/zones/zone/zone-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</a>
<a
*ngIf="showCloseIcon"
[routerLink]="['..']"
appBackLink=".."
class="text-blue-500 hover:text-primary text-2xl cursor-pointer ml-4"
i18n-title
title="Close zone detail view">
Expand Down

0 comments on commit d89d9ce

Please sign in to comment.