Add navigation flag to return to custom oriring
Adds the state "back: 'true'" to certain router navigations to set a custom return point for using the OpenSlides back arrow. Allows to return to category detail, motion block detail and amendment detail from a motion detail view. You will keep the navigation state for as long as you don't change the view
This commit is contained in:
parent
b86054c4b9
commit
ce2f711a7c
@ -17,6 +17,11 @@ export class RoutingStateService {
|
||||
*/
|
||||
private _previousUrl: string;
|
||||
|
||||
/**
|
||||
* Stores the routing state
|
||||
*/
|
||||
private _customOrigin: string;
|
||||
|
||||
/**
|
||||
* Unsafe paths that the user should not go "back" to
|
||||
* TODO: Might also work using Routing parameters
|
||||
@ -39,6 +44,10 @@ export class RoutingStateService {
|
||||
return this._previousUrl;
|
||||
}
|
||||
|
||||
public get customOrigin(): string {
|
||||
return this._customOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch routing changes and save the last visited URL
|
||||
*
|
||||
@ -52,10 +61,33 @@ export class RoutingStateService {
|
||||
)
|
||||
.subscribe((event: any[]) => {
|
||||
this._previousUrl = event[0].urlAfterRedirects;
|
||||
if (
|
||||
this.router.getCurrentNavigation().extras &&
|
||||
this.router.getCurrentNavigation().extras.state &&
|
||||
this.router.getCurrentNavigation().extras.state.back
|
||||
) {
|
||||
this._customOrigin = this._previousUrl;
|
||||
} else if (
|
||||
this._customOrigin &&
|
||||
!this.isSameComponent(event[0].urlAfterRedirects, event[1].urlAfterRedirects)
|
||||
) {
|
||||
this._customOrigin = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public goBack(): void {
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyse the URL to check if you were navigating using the same components
|
||||
*/
|
||||
private isSameComponent(urlA: string, urlB: string): boolean {
|
||||
const pathA = urlA.slice(0, urlA.lastIndexOf('/'));
|
||||
const pathB = urlB.slice(0, urlB.lastIndexOf('/'));
|
||||
const paramA = urlA.slice(urlA.lastIndexOf('/') + 1);
|
||||
const paramB = urlB.slice(urlA.lastIndexOf('/') + 1);
|
||||
return pathA === pathB && !isNaN(+paramA) && !isNaN(+paramB);
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +222,8 @@ export class HeadBarComponent implements OnInit {
|
||||
public onBackButton(): void {
|
||||
if (this.goBack) {
|
||||
this.routingState.goBack();
|
||||
} else if (this.routingState.customOrigin && this.routingState.customOrigin !== this.router.url) {
|
||||
this.router.navigate([this.routingState.customOrigin], { relativeTo: this.route });
|
||||
} else {
|
||||
this.router.navigate([this.prevUrl], { relativeTo: this.route });
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<os-head-bar [nav]="false" [multiSelectMode]="isMultiSelect" goBack="true">
|
||||
<os-head-bar prevUrl="../.." [nav]="false" [multiSelectMode]="isMultiSelect">
|
||||
<!-- Title -->
|
||||
<div class="title-slot" *ngIf="!parentMotion"><h2 translate>Amendments</h2></div>
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
>
|
||||
<!-- Meta -->
|
||||
<div *pblNgridCellDef="'meta'; row as motion" class="cell-slot fill">
|
||||
<a class="detail-link" [routerLink]="motion.getDetailStateURL()"></a>
|
||||
<a class="detail-link" [routerLink]="motion.getDetailStateURL()" [state]="{ back: 'true' }"></a>
|
||||
<div class="innerTable">
|
||||
<!-- Identifier and line -->
|
||||
<div class="title-line one-line">
|
||||
|
@ -55,7 +55,7 @@
|
||||
<ng-container matColumnDef="anchor">
|
||||
<mat-header-cell *matHeaderCellDef></mat-header-cell>
|
||||
<mat-cell *matCellDef="let motion">
|
||||
<a [routerLink]="motion.getDetailStateURL()"></a>
|
||||
<a [routerLink]="motion.getDetailStateURL()" [state]="{ back: 'true' }"></a>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
|
@ -40,7 +40,12 @@
|
||||
>
|
||||
<!-- Title column -->
|
||||
<div *pblNgridCellDef="'title'; row as motion; rowContext as rowContext" class="cell-slot fill">
|
||||
<a class="detail-link" [routerLink]="motion.getDetailStateURL()" *ngIf="!isMultiSelect"></a>
|
||||
<a
|
||||
class="detail-link"
|
||||
[routerLink]="motion.getDetailStateURL()"
|
||||
[state]="{ back: 'true' }"
|
||||
*ngIf="!isMultiSelect"
|
||||
></a>
|
||||
<div class="column-title innerTable">
|
||||
<div class="title-line ellipsis-overflow">
|
||||
<!-- Is Favorite -->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<os-head-bar
|
||||
[hasMainButton]="perms.isAllowed('can_create_amendments', motion)"
|
||||
mainActionTooltip="New amendment"
|
||||
[prevUrl]="getPrevUrl()"
|
||||
prevUrl="../.."
|
||||
[nav]="false"
|
||||
[editMode]="editMotion"
|
||||
[isSaveButtonEnabled]="contentForm.valid"
|
||||
@ -144,9 +144,12 @@
|
||||
<span *ngIf="showSequential && motion.parent_id">· </span>
|
||||
<span *ngIf="motion.parent_id">
|
||||
<span>
|
||||
<span translate>Amendment to</span> <a [routerLink]="motion.parent.getDetailStateURL()">{{
|
||||
motion.parent.identifier || motion.parent.title
|
||||
}}</a>
|
||||
<span translate>Amendment to</span> <a
|
||||
[routerLink]="motion.parent.getDetailStateURL()"
|
||||
[state]="{ back: 'true' }"
|
||||
>
|
||||
{{ motion.parent.identifier || motion.parent.title }}
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
@ -440,7 +443,7 @@
|
||||
<!-- Ammendments -->
|
||||
<div *ngIf="!editMotion && amendments && amendments.length > 0">
|
||||
<h4 translate>Amendments</h4>
|
||||
<a [routerLink]="['/motions/amendments', motion.id]">
|
||||
<a [routerLink]="['/motions/amendments', motion.id]" [state]="{ back: 'true' }">
|
||||
{{ amendments.length }}
|
||||
<span *ngIf="amendments.length === 1" translate>Amendment</span>
|
||||
<span *ngIf="amendments.length > 1" translate>Amendments</span>
|
||||
@ -621,12 +624,7 @@
|
||||
<!-- Title -->
|
||||
<div *ngIf="editMotion" class="content-field form-title">
|
||||
<mat-form-field *ngIf="editMotion">
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'Title' | translate }}"
|
||||
formControlName="title"
|
||||
required
|
||||
/>
|
||||
<input matInput placeholder="{{ 'Title' | translate }}" formControlName="title" required />
|
||||
<mat-error>{{ 'The title is required' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@ -839,11 +837,7 @@
|
||||
<div class="content-field" *ngIf="editMotion">
|
||||
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'Origin' | translate }}"
|
||||
formControlName="origin"
|
||||
/>
|
||||
<input matInput placeholder="{{ 'Origin' | translate }}" formControlName="origin" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,7 +35,6 @@ import { DiffLinesInParagraph, LineRange } from 'app/core/ui-services/diff.servi
|
||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||
import { PersonalNoteService } from 'app/core/ui-services/personal-note.service';
|
||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||
import { RoutingStateService } from 'app/core/ui-services/routing-state.service';
|
||||
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||
import { Motion } from 'app/shared/models/motions/motion';
|
||||
@ -451,7 +450,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
private itemRepo: ItemRepositoryService,
|
||||
private motionSortService: MotionSortListService,
|
||||
private motionFilterService: MotionFilterListService,
|
||||
private routingStateService: RoutingStateService,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(title, translate, matSnackBar);
|
||||
@ -1538,30 +1536,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
||||
this.raiseError(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to determine the previous URL if it's considered unsafe
|
||||
*
|
||||
* @returns the target to navigate to
|
||||
*/
|
||||
public getPrevUrl(): string {
|
||||
if (this.motion && this.motion.parent_id) {
|
||||
if (this.routingStateService.previousUrl && this.routingStateService.isSafePrevUrl) {
|
||||
if (
|
||||
(this.previousMotion &&
|
||||
this.routingStateService.previousUrl === this.previousMotion.getDetailStateURL()) ||
|
||||
(this.nextMotion && this.routingStateService.previousUrl === this.nextMotion.getDetailStateURL())
|
||||
) {
|
||||
return '../..';
|
||||
} else {
|
||||
return this.routingStateService.previousUrl;
|
||||
}
|
||||
} else {
|
||||
return this.motion.parent.getDetailStateURL();
|
||||
}
|
||||
}
|
||||
return '../..';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to prevent automatically closing the window/tab,
|
||||
* if the user is editing a motion.
|
||||
|
Loading…
Reference in New Issue
Block a user