Skip to content

Commit

Permalink
Merge pull request #134 from Apes2getherStrong/wtg-51-alert-when-leav…
Browse files Browse the repository at this point in the history
…ing-edit-without-saving

Wtg 51 alert when leaving edit without saving
  • Loading branch information
Kondziow authored Sep 30, 2024
2 parents 05cb648 + 8d18bec commit b987c14
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 26 deletions.
10 changes: 8 additions & 2 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {RegisterComponent} from "./user/register/register.component";
import {MapLocationEditComponent} from "./map-location/map-location-edit/map-location-edit.component";
import {AuthGuardService} from "./auth/auth-guard.service";
import {CanEditService} from "./auth/can-edit.service";
import {CanDeactivateGuard} from "./shared/guards/can-deactivate-guard.service";



Expand All @@ -29,21 +30,25 @@ const routes: Routes = [
path: 'point/new/:routeId',
canActivate: [AuthGuardService],
component: MapLocationEditComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: 'point/:pointId/edit',
canActivate: [AuthGuardService],
component: MapLocationEditComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: 'routes/new',
canActivate: [AuthGuardService],
component: RouteEditComponent
component: RouteEditComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: 'yourRoutes/new',
canActivate: [AuthGuardService],
component: RouteEditComponent
component: RouteEditComponent,
canDeactivate: [CanDeactivateGuard]
},
{
path: 'users/:id',
Expand Down Expand Up @@ -100,6 +105,7 @@ const routes: Routes = [
{
path: 'yourRoutes/:id/edit',
canActivate: [AuthGuardService,CanEditService],
canDeactivate: [CanDeactivateGuard],
component: RouteEditComponent
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {DomSanitizer, SafeUrl} from "@angular/platform-browser";
import {Audio} from "../../audio/audio.model";
import {AudioService} from "../../audio/audio.service";
import {maxPageSize} from "../../shared/http.config";
import {CanComponentDeactivate} from "../../shared/guards/can-deactivate-guard.service";
import {CanDeactivateFormGuardService} from "../../shared/guards/can-deactivate-form-guard.service";
import {ConfirmationDialogService} from "../../shared/confirmation-dialog/confirmation-dialog.service";


@Component({
Expand All @@ -25,7 +28,7 @@ import {maxPageSize} from "../../shared/http.config";
templateUrl: './map-location-edit.component.html',
styleUrl: './map-location-edit.component.css'
})
export class MapLocationEditComponent implements OnInit {
export class MapLocationEditComponent implements OnInit, CanComponentDeactivate {
@ViewChild('audioFileInput') audioFileInput: ElementRef;
routeId: string;
mapLocationId: string;
Expand All @@ -43,14 +46,17 @@ export class MapLocationEditComponent implements OnInit {
selectedAudioFile: File | null = null;
temporaryAudioData: { audio: Audio, url: SafeUrl,file: File }[] = [];
returnUrl: string | null = null;
private submittingChangesInProcess: boolean = false;

constructor(private activatedRoute: ActivatedRoute,
private router: Router,
private mapService: PointSelectMapService,
private mapLocationService: MapLocationService,
private routeMapLocationService: RouteMapLocationService,
private audioService: AudioService,
private sanitizer: DomSanitizer) {
private sanitizer: DomSanitizer,
private canDeactivateFormGuardService: CanDeactivateFormGuardService,
private confirmationDialogService: ConfirmationDialogService,) {
}

ngOnInit(): void {
Expand Down Expand Up @@ -93,8 +99,13 @@ export class MapLocationEditComponent implements OnInit {
});
})

}


canDeactivate(): Promise<boolean> {
if(this.submittingChangesInProcess) {
return Promise.resolve(true);
}
return this.canDeactivateFormGuardService.canDeactivateForm(this.mapLocationForm.dirty && !this.mapLocationForm.pristine);
}


Expand Down Expand Up @@ -157,6 +168,7 @@ export class MapLocationEditComponent implements OnInit {
}

onSubmit() {
this.submittingChangesInProcess = true;
let newMapLocation = {
name: this.mapLocationForm.value.name,
description: this.mapLocationForm.value.description,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {ModalService} from "../../shared/modal/modal.service";
import {
MapLocationAddToYourRouteModalComponent
} from "../map-location-add-to-your-route-modal/map-location-add-to-your-route-modal.component";
import {ConfirmationDialogService} from "../../shared/confirmation-dialog/confirmation-dialog.service";

@Component({
selector: 'app-map-location-list',
Expand Down Expand Up @@ -55,7 +56,8 @@ export class MapLocationListComponent implements OnInit, OnChanges {
private router: Router,
private modalService: ModalService,
private activatedRoute: ActivatedRoute,
private routeService: RouteService) {
private routeService: RouteService,
private confirmationDialogService: ConfirmationDialogService) {
}


Expand Down Expand Up @@ -106,11 +108,21 @@ export class MapLocationListComponent implements OnInit, OnChanges {
}

onMapLocationDelete(mapLocationId: string) {
if (confirm("You are about to delete map location. Do you want to continue?")) {
this.mapLocationService.deleteMapLocationFromRoute(mapLocationId, this.route.id).subscribe(() => {
this.fetchMapLocations();

this.confirmationDialogService
.confirm(
'Confirm Deletion',
`You are about to delete your map location. Do you want to proceed?`,
'Yes',
'Cancel'
)
.subscribe((confirmed: boolean) => {
if (confirmed) {
this.mapLocationService.deleteMapLocationFromRoute(mapLocationId, this.route.id).subscribe(() => {
this.fetchMapLocations();
});
}
});
}
}

onAddToYourRoute(mapLocation : MapLocation) {
Expand Down
62 changes: 46 additions & 16 deletions src/app/route/route-edit/route-edit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import { Location, NgForOf, NgIf } from "@angular/common";
import { maxPageSize } from "../../shared/http.config";
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import {MapLocationListComponent} from "../../map-location/map-location-list/map-location-list.component";
import {CanComponentDeactivate} from "../../shared/guards/can-deactivate-guard.service";
import {CanDeactivateFormGuardService} from "../../shared/guards/can-deactivate-form-guard.service";
import {catchError, of} from "rxjs";
import {MapLocationConflictError} from "../../shared/errors/route-map-location-conflict.error";
import {SnackbarType} from "../../shared/snackbar/snackbar-type";
import {ConfirmationDialogService} from "../../shared/confirmation-dialog/confirmation-dialog.service";

@Component({
selector: 'app-route-edit',
Expand All @@ -22,7 +28,7 @@ import {MapLocationListComponent} from "../../map-location/map-location-list/map
templateUrl: './route-edit.component.html',
styleUrl: './route-edit.component.css'
})
export class RouteEditComponent implements OnInit {
export class RouteEditComponent implements OnInit, CanComponentDeactivate {
id: string;
routeForm: FormGroup;
userLogin: string;
Expand All @@ -32,13 +38,15 @@ export class RouteEditComponent implements OnInit {
selectedFile: File = null;
currentImageUrl: SafeUrl = null;
imagePreview: string | ArrayBuffer | null = null;
private submittingChangesInProcess: boolean = false;

constructor(private routeService: RouteService,
private mapLocationService: MapLocationService,
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
private sanitizer: DomSanitizer) {
private sanitizer: DomSanitizer,
private canDeactivateFormGuardService: CanDeactivateFormGuardService,
private confirmationDialogService: ConfirmationDialogService,) {
}

ngOnInit() {
Expand All @@ -56,20 +64,31 @@ export class RouteEditComponent implements OnInit {
}
}

canDeactivate(): Promise<boolean> {
if(this.submittingChangesInProcess) {
return Promise.resolve(true);
}
return this.canDeactivateFormGuardService.canDeactivateForm(this.routeForm.dirty && !this.routeForm.pristine);
}


onFileSelected(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
this.selectedFile = input.files[0];
}

const reader = new FileReader();
reader.onload = () => {
this.imagePreview = reader.result;
};
reader.readAsDataURL(this.selectedFile);
this.routeForm.markAsDirty();

const reader = new FileReader();
reader.onload = () => {
this.imagePreview = reader.result;
};
reader.readAsDataURL(this.selectedFile);
}
}

onSubmit() {
this.submittingChangesInProcess = true;
if (this.editMode) {
this.routeService.patchRouteById(this.id, this.routeForm.value)
.subscribe(() => {
Expand All @@ -92,7 +111,7 @@ export class RouteEditComponent implements OnInit {
this.goBack();
});
} else {
this.goBack();
this.router.navigate(['yourRoutes', 'list']);
}
});
}
Expand All @@ -107,12 +126,23 @@ export class RouteEditComponent implements OnInit {
}

onDelete() {
if (confirm("You are about to delete " + this.route.name + " route. Do you want to continue?")) {
this.routeService.deleteRouteById(this.id)
.subscribe(() => {
this.router.navigate(['../../', 'list'], { relativeTo: this.activatedRoute });
});
}
this.submittingChangesInProcess = true;

this.confirmationDialogService
.confirm(
'Confirm Deletion',
`You are about to delete your route. Do you want to proceed?`,
'Yes',
'Cancel'
)
.subscribe((confirmed: boolean) => {
if (confirmed) {
this.routeService.deleteRouteById(this.id)
.subscribe(() => {
this.router.navigate(['../../', 'list'], { relativeTo: this.activatedRoute });
});
}
});
}


Expand Down
29 changes: 29 additions & 0 deletions src/app/shared/guards/can-deactivate-form-guard.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {Injectable} from "@angular/core";
import {ConfirmationDialogService} from "../confirmation-dialog/confirmation-dialog.service";

@Injectable({
providedIn: 'root',
})
export class CanDeactivateFormGuardService {

constructor(private confirmationDialogService: ConfirmationDialogService) {}

canDeactivateForm(isDirty: boolean):Promise<boolean> {
if (isDirty) {
return new Promise((resolve) => {
this.confirmationDialogService
.confirm(
'Confirm Exiting',
`You are about to exit without saving the changes. Do you want to proceed?`,
'Yes',
'Cancel'
)
.subscribe((confirmed: boolean) => {
resolve(confirmed);
});
});
} else {
return Promise.resolve(true);
}
}
}
16 changes: 16 additions & 0 deletions src/app/shared/guards/can-deactivate-guard.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Observable} from "rxjs";
import {Injectable} from "@angular/core";
import {CanDeactivate} from "@angular/router";

export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate (component: CanComponentDeactivate) : Observable<boolean> | Promise<boolean> | boolean {
return component.canDeactivate();
}
}

0 comments on commit b987c14

Please sign in to comment.