Pull request #80: RED-898: Warning message on unsaved changes
Merge in RED/ui from RED-898 to master * commit '455949e4fd60b002e496b00c281c5552e009ea24': Warning message on unsaved changes
This commit is contained in:
commit
ac175d2bfd
@ -98,6 +98,7 @@ import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug
|
|||||||
import { ReportDownloadBtnComponent } from './components/buttons/report-download-btn/report-download-btn.component';
|
import { ReportDownloadBtnComponent } from './components/buttons/report-download-btn/report-download-btn.component';
|
||||||
import { ProjectListingActionsComponent } from './screens/project-listing-screen/project-listing-actions/project-listing-actions.component';
|
import { ProjectListingActionsComponent } from './screens/project-listing-screen/project-listing-actions/project-listing-actions.component';
|
||||||
import { HasScrollbarDirective } from './utils/has-scrollbar.directive';
|
import { HasScrollbarDirective } from './utils/has-scrollbar.directive';
|
||||||
|
import { PendingChangesGuard } from './utils/can-deactivate.guard';
|
||||||
|
|
||||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||||
@ -179,6 +180,7 @@ const routes = [
|
|||||||
path: 'dictionaries/:type',
|
path: 'dictionaries/:type',
|
||||||
component: DictionaryOverviewScreenComponent,
|
component: DictionaryOverviewScreenComponent,
|
||||||
canActivate: [CompositeRouteGuard],
|
canActivate: [CompositeRouteGuard],
|
||||||
|
canDeactivate: [PendingChangesGuard],
|
||||||
data: {
|
data: {
|
||||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
||||||
}
|
}
|
||||||
@ -195,6 +197,7 @@ const routes = [
|
|||||||
path: 'rules',
|
path: 'rules',
|
||||||
component: RulesScreenComponent,
|
component: RulesScreenComponent,
|
||||||
canActivate: [CompositeRouteGuard],
|
canActivate: [CompositeRouteGuard],
|
||||||
|
canDeactivate: [PendingChangesGuard],
|
||||||
data: {
|
data: {
|
||||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { NotificationService, NotificationType } from '../../../notification/not
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
|
import { ComponentHasChanges } from '../../../utils/can-deactivate.guard';
|
||||||
|
|
||||||
declare var ace;
|
declare var ace;
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ declare var ace;
|
|||||||
templateUrl: './dictionary-overview-screen.component.html',
|
templateUrl: './dictionary-overview-screen.component.html',
|
||||||
styleUrls: ['./dictionary-overview-screen.component.scss']
|
styleUrls: ['./dictionary-overview-screen.component.scss']
|
||||||
})
|
})
|
||||||
export class DictionaryOverviewScreenComponent {
|
export class DictionaryOverviewScreenComponent extends ComponentHasChanges {
|
||||||
static readonly MIN_WORD_LENGTH: number = 2;
|
static readonly MIN_WORD_LENGTH: number = 2;
|
||||||
public compareActive = false;
|
public compareActive = false;
|
||||||
|
|
||||||
@ -49,13 +50,14 @@ export class DictionaryOverviewScreenComponent {
|
|||||||
constructor(
|
constructor(
|
||||||
public readonly permissionsService: PermissionsService,
|
public readonly permissionsService: PermissionsService,
|
||||||
private readonly _notificationService: NotificationService,
|
private readonly _notificationService: NotificationService,
|
||||||
private readonly _translateService: TranslateService,
|
protected readonly _translateService: TranslateService,
|
||||||
private readonly _dictionaryControllerService: DictionaryControllerService,
|
private readonly _dictionaryControllerService: DictionaryControllerService,
|
||||||
private readonly _dialogService: DialogService,
|
private readonly _dialogService: DialogService,
|
||||||
private readonly _router: Router,
|
private readonly _router: Router,
|
||||||
private readonly _activatedRoute: ActivatedRoute,
|
private readonly _activatedRoute: ActivatedRoute,
|
||||||
private readonly _appStateService: AppStateService
|
private readonly _appStateService: AppStateService
|
||||||
) {
|
) {
|
||||||
|
super(_translateService);
|
||||||
this._activatedRoute.params.subscribe((params) => {
|
this._activatedRoute.params.subscribe((params) => {
|
||||||
this.dictionary = this._appStateService.dictionaryData[params.type];
|
this.dictionary = this._appStateService.dictionaryData[params.type];
|
||||||
if (!this.dictionary) {
|
if (!this.dictionary) {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { RulesControllerService } from '@redaction/red-ui-http';
|
|||||||
import { NotificationService, NotificationType } from '../../../notification/notification.service';
|
import { NotificationService, NotificationType } from '../../../notification/notification.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
|
import { ComponentHasChanges } from '../../../utils/can-deactivate.guard';
|
||||||
|
|
||||||
declare var ace;
|
declare var ace;
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ declare var ace;
|
|||||||
templateUrl: './rules-screen.component.html',
|
templateUrl: './rules-screen.component.html',
|
||||||
styleUrls: ['./rules-screen.component.scss']
|
styleUrls: ['./rules-screen.component.scss']
|
||||||
})
|
})
|
||||||
export class RulesScreenComponent {
|
export class RulesScreenComponent extends ComponentHasChanges {
|
||||||
public aceOptions = { showPrintMargin: false };
|
public aceOptions = { showPrintMargin: false };
|
||||||
public rules: string;
|
public rules: string;
|
||||||
public processing = true;
|
public processing = true;
|
||||||
@ -33,8 +34,9 @@ export class RulesScreenComponent {
|
|||||||
public readonly permissionsService: PermissionsService,
|
public readonly permissionsService: PermissionsService,
|
||||||
private readonly _rulesControllerService: RulesControllerService,
|
private readonly _rulesControllerService: RulesControllerService,
|
||||||
private readonly _notificationService: NotificationService,
|
private readonly _notificationService: NotificationService,
|
||||||
private readonly _translateService: TranslateService
|
protected readonly _translateService: TranslateService
|
||||||
) {
|
) {
|
||||||
|
super(_translateService);
|
||||||
this._initialize();
|
this._initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
apps/red-ui/src/app/utils/can-deactivate.guard.ts
Normal file
38
apps/red-ui/src/app/utils/can-deactivate.guard.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { CanDeactivate } from '@angular/router';
|
||||||
|
import { Directive, HostListener, Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
export interface ComponentCanDeactivate {
|
||||||
|
hasChanges: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive()
|
||||||
|
export abstract class ComponentHasChanges implements ComponentCanDeactivate {
|
||||||
|
abstract hasChanges: boolean;
|
||||||
|
|
||||||
|
protected constructor(protected _translateService: TranslateService) {}
|
||||||
|
|
||||||
|
@HostListener('window:beforeunload', ['$event'])
|
||||||
|
unloadNotification($event: any) {
|
||||||
|
if (this.hasChanges) {
|
||||||
|
// This message will be displayed in IE/Edge
|
||||||
|
$event.returnValue = this._translateService.instant('pending-changes-guard');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
|
||||||
|
constructor(private readonly translateService: TranslateService) {}
|
||||||
|
|
||||||
|
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
|
||||||
|
// if there are no pending changes, just allow deactivation; else confirm first
|
||||||
|
return !component.hasChanges
|
||||||
|
? true
|
||||||
|
: // NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
|
||||||
|
// when navigating away from your angular app, the browser will show a generic warning message
|
||||||
|
// see http://stackoverflow.com/a/42207299/7307355
|
||||||
|
confirm(this.translateService.instant('pending-changes-guard'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -650,5 +650,6 @@
|
|||||||
"mark-unread": "Mark as unread"
|
"mark-unread": "Mark as unread"
|
||||||
},
|
},
|
||||||
"rule-editor": "Rule Editor",
|
"rule-editor": "Rule Editor",
|
||||||
"watermark": "Watermark"
|
"watermark": "Watermark",
|
||||||
|
"pending-changes-guard": "WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes."
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user