Adds dialog to ask user for confirmation before leaving. (Issue #166)
This commit is contained in:
parent
aaa1e9d1c7
commit
27ce739382
|
@ -1,17 +1,27 @@
|
|||
<div class="confirmation-dialog">
|
||||
<div *ngIf="data.icon" class="row d-flex flex-row">
|
||||
<div class="col-auto close-btn justify-content-start">
|
||||
<mat-icon color="warn">{{ data.icon }}</mat-icon>
|
||||
</div>
|
||||
<div *ngIf="data.warning" class="col justify-content-center warn-text">
|
||||
{{ data.warning }}
|
||||
</div>
|
||||
<div class="col-auto close-btn justify-content-end" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row d-flex flex-row">
|
||||
<div class="col confirmation-message">
|
||||
{{ data.message }}
|
||||
</div>
|
||||
<div class="col-auto close-btn" (click)="close()"><mat-icon>close</mat-icon></div>
|
||||
<div *ngIf="!data.icon" class="col-auto close-btn justify-content-end" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
<div class="col-auto"><button mat-raised-button type="button" (click)="cancel()"
|
||||
class="cancel">{{ data.cancelButton }}</button></div>
|
||||
<div *ngIf="data.isDeleteConfirmation" class="col-auto"><button mat-raised-button type="button" (click)="confirm()"
|
||||
class="delete">{{ data.confirmButton }}</button></div>
|
||||
<div *ngIf="!data.isDeleteConfirmation" class="col-auto"><button mat-raised-button type="button" (click)="confirm()"
|
||||
class="confirm">{{ data.confirmButton }}</button></div>
|
||||
<div class="col-auto"><button mat-raised-button type="button" (click)="cancel()" class="cancel">{{ data.cancelButton }}</button></div>
|
||||
<div *ngIf="data.isDeleteConfirmation" class="col-auto"><button mat-raised-button type="button" (click)="confirm()" class="delete">{{ data.confirmButton }}</button></div>
|
||||
<div *ngIf="!data.isDeleteConfirmation" class="col-auto"><button mat-raised-button type="button" (click)="confirm()" class="confirm">{{ data.confirmButton }}</button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.warn-text {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
background-color: #aaaaaa;
|
||||
color: #ffffff;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { CanDeactivate } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { BaseComponent } from '../../core/common/base/base.component';
|
||||
import { CheckDeactivateBaseComponent } from './deactivate.component';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
|
||||
@Injectable()
|
||||
export class CanDeactivateGuard extends BaseComponent implements CanDeactivate<CheckDeactivateBaseComponent> {
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
public language: TranslateService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
canDeactivate(component: CheckDeactivateBaseComponent): boolean | Observable<boolean> {
|
||||
|
||||
if (component.canDeactivate()) {
|
||||
return true;
|
||||
} else {
|
||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
maxWidth: '700px',
|
||||
data: {
|
||||
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.LEAVE-PAGE'),
|
||||
warning: this.language.instant('GENERAL.CONFIRMATION-DIALOG.LEAVE-WARNING'),
|
||||
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
|
||||
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.LEAVE'),
|
||||
icon: 'error_outline'
|
||||
}
|
||||
});
|
||||
return dialogRef.afterClosed().pipe(map(x => x ? true : false));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { BaseComponent } from '../../core/common/base/base.component';
|
||||
import { HostListener } from '@angular/core';
|
||||
|
||||
export abstract class CheckDeactivateBaseComponent extends BaseComponent {
|
||||
|
||||
protected constructor() { super(); }
|
||||
|
||||
abstract canDeactivate(): boolean;
|
||||
|
||||
@HostListener('window:beforeunload', ['$event'])
|
||||
unloadNotification($event: any) {
|
||||
if (!this.canDeactivate()) {
|
||||
$event.returnValue = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import {of as observableOf, Observable } from 'rxjs';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
@ -16,17 +16,19 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { DatasetEditorWizardComponent } from '../quick-wizard/dataset-editor/dataset-editor-wizard.component';
|
||||
import { DatasetStatus } from '../../core/common/enum/dataset-status';
|
||||
import { ConfirmationDialogComponent } from '../../library/confirmation-dialog/confirmation-dialog.component';
|
||||
import { CheckDeactivateBaseComponent } from '../../library/deactivate/deactivate.component';
|
||||
|
||||
@Component({
|
||||
selector: 'dataset-create-wizard.component',
|
||||
templateUrl: 'dataset-create-wizard.component.html',
|
||||
styleUrls: ['./dataset-create-wizard.component.scss'],
|
||||
})
|
||||
export class DatasetCreateWizard extends BaseComponent implements OnInit, IBreadCrumbComponent {
|
||||
export class DatasetCreateWizard extends CheckDeactivateBaseComponent implements OnInit, IBreadCrumbComponent {
|
||||
breadCrumbs: Observable<BreadcrumbItem[]>;
|
||||
@ViewChild(DatasetEditorWizardComponent, { static: false }) datasetEditorWizardComponent: DatasetEditorWizardComponent;
|
||||
isLinear = false;
|
||||
isNew = true;
|
||||
isSubmitted = false;
|
||||
formGroup: FormGroup;
|
||||
|
||||
|
||||
|
@ -70,7 +72,8 @@ export class DatasetCreateWizard extends BaseComponent implements OnInit, IBread
|
|||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
complete => this.onCallbackSuccess(dmpId)
|
||||
)
|
||||
);
|
||||
this.isSubmitted = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -128,7 +131,8 @@ export class DatasetCreateWizard extends BaseComponent implements OnInit, IBread
|
|||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
complete => this.onCallbackSuccess(dmpId)
|
||||
)
|
||||
);
|
||||
this.isSubmitted = true;
|
||||
}
|
||||
|
||||
hasDatasets() {
|
||||
|
@ -156,4 +160,8 @@ export class DatasetCreateWizard extends BaseComponent implements OnInit, IBread
|
|||
return this.stepper.selectedIndex == 1;
|
||||
}
|
||||
}
|
||||
|
||||
canDeactivate(): boolean {
|
||||
return this.isSubmitted || !this.formGroup.dirty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ import { ConfirmationDialogModule } from '../../library/confirmation-dialog/conf
|
|||
import { UrlListingModule } from '../../library/url-listing/url-listing.module';
|
||||
import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/dataset-description-form.module';
|
||||
import { OuickWizardModule } from '../quick-wizard/quick-wizard.module';
|
||||
import { QuickWizardRoutingModule } from '../quick-wizard/quick-wizard.rooting';
|
||||
import { DatasetCreateWizard } from './dataset-create-wizard.component';
|
||||
import { DatasetCreateWizardRoutingModule } from './dataset-create-wizard.routing';
|
||||
import { DatasetDmpSelector } from './dmp-selector/dataset-dmp-selector.component';
|
||||
import { QuickWizardRoutingModule } from '../quick-wizard/quick-wizard.routing';
|
||||
import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard';
|
||||
|
||||
|
||||
@NgModule({
|
||||
|
@ -32,6 +33,9 @@ import { DatasetDmpSelector } from './dmp-selector/dataset-dmp-selector.componen
|
|||
DatasetDmpSelector,
|
||||
],
|
||||
entryComponents: [
|
||||
],
|
||||
providers: [
|
||||
CanDeactivateGuard
|
||||
]
|
||||
})
|
||||
export class DatasetCreateWizardModule { }
|
||||
|
|
|
@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
|
|||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { DatasetCreateWizard } from './dataset-create-wizard.component';
|
||||
import { DatasetDmpSelector } from './dmp-selector/dataset-dmp-selector.component';
|
||||
import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
|
@ -10,6 +11,7 @@ const routes: Routes = [
|
|||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
canDeactivate: [CanDeactivateGuard]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
import {of as observableOf, Observable } from 'rxjs';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { of as observableOf, Observable } from 'rxjs';
|
||||
import { Component, OnInit, ViewChild, HostListener } from '@angular/core';
|
||||
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
|
@ -24,18 +24,20 @@ import { GrantEditorWizardModel } from '../grant-editor/grant-editor-wizard-mode
|
|||
import { QuickWizardEditorWizardModel } from './quick-wizard-editor.model';
|
||||
import { FunderFormModel } from '../../dmp/editor/grant-tab/funder-form-model';
|
||||
import { ProjectFormModel } from '../../dmp/editor/grant-tab/project-form-model';
|
||||
import { CheckDeactivateBaseComponent } from '../../../library/deactivate/deactivate.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-quick-wizard-editor-component',
|
||||
templateUrl: 'quick-wizard-editor.component.html',
|
||||
styleUrls: ['./quick-wizard-editor.component.scss']
|
||||
})
|
||||
export class QuickWizardEditorComponent extends BaseComponent implements OnInit, IBreadCrumbComponent {
|
||||
export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent implements OnInit, IBreadCrumbComponent {
|
||||
|
||||
breadCrumbs: Observable<BreadcrumbItem[]> = observableOf([]);
|
||||
@ViewChild('stepper', { static: true }) stepper: MatStepper;
|
||||
@ViewChild(DatasetEditorWizardComponent, { static: false }) datasetEditorWizardComponent: DatasetEditorWizardComponent;
|
||||
isNew = true;
|
||||
isSubmitted = false;
|
||||
quickWizard: QuickWizardEditorWizardModel;
|
||||
allDatasets: DmpFinalizeDialogDataset[] = [];
|
||||
formGroup: FormGroup = null;
|
||||
|
@ -155,6 +157,7 @@ export class QuickWizardEditorComponent extends BaseComponent implements OnInit,
|
|||
complete => this.onCallbackSuccess(),
|
||||
error => this.onCallbackError(error)
|
||||
);
|
||||
this.isSubmitted = true;
|
||||
}
|
||||
|
||||
onSubmitSave(): void {
|
||||
|
@ -175,6 +178,7 @@ export class QuickWizardEditorComponent extends BaseComponent implements OnInit,
|
|||
.subscribe(
|
||||
complete => this.onCallbackSuccess()
|
||||
)
|
||||
this.isSubmitted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -217,4 +221,8 @@ export class QuickWizardEditorComponent extends BaseComponent implements OnInit,
|
|||
return this.formGroup.get('grant').get('label').value;
|
||||
}
|
||||
}
|
||||
|
||||
canDeactivate(): boolean {
|
||||
return this.isSubmitted || !this.formGroup.dirty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { CommonFormsModule } from '../../common/forms/common-forms.module';
|
|||
import { CommonUiModule } from '../../common/ui/common-ui.module';
|
||||
import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module';
|
||||
import { UrlListingModule } from '../../library/url-listing/url-listing.module';
|
||||
import { QuickWizardRoutingModule } from './quick-wizard.rooting';
|
||||
import { QuickWizardRoutingModule } from './quick-wizard.routing';
|
||||
import { GrantEditorWizardComponent } from './grant-editor/grant-editor-wizard.component';
|
||||
import { DmpEditorWizardComponent } from './dmp-editor/dmp-editor-wizard.component';
|
||||
import { QuickWizardEditorComponent } from './quick-wizard-editor/quick-wizard-editor.component';
|
||||
|
@ -13,7 +13,7 @@ import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/d
|
|||
import { DmpModule } from '../dmp/dmp.module';
|
||||
import { FunderEditorWizardComponent } from './funder-editor/funder-editor-wizard.component';
|
||||
import { ProjectEditorWizardComponent } from './project-editor/project-editor-wizard.component';
|
||||
|
||||
import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -36,6 +36,9 @@ import { ProjectEditorWizardComponent } from './project-editor/project-editor-wi
|
|||
],
|
||||
exports: [
|
||||
DatasetEditorWizardComponent,
|
||||
],
|
||||
providers: [
|
||||
CanDeactivateGuard
|
||||
]
|
||||
})
|
||||
export class OuickWizardModule { }
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { DmpEditorWizardComponent } from './dmp-editor/dmp-editor-wizard.component';
|
||||
import { GrantEditorWizardComponent } from './grant-editor/grant-editor-wizard.component';
|
||||
import { QuickWizardEditorComponent } from './quick-wizard-editor/quick-wizard-editor.component';
|
||||
import { DatasetEditorWizardComponent } from './dataset-editor/dataset-editor-wizard.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: QuickWizardEditorComponent,
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},{
|
||||
path: 'grant',
|
||||
component: GrantEditorWizardComponent,
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'dmp',
|
||||
component: DmpEditorWizardComponent,
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'dataset',
|
||||
component: DatasetEditorWizardComponent,
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class QuickWizardRoutingModule { }
|
|
@ -0,0 +1,42 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { QuickWizardEditorComponent } from './quick-wizard-editor/quick-wizard-editor.component';
|
||||
import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: QuickWizardEditorComponent,
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
canDeactivate: [CanDeactivateGuard]
|
||||
},
|
||||
// {
|
||||
// path: 'grant',
|
||||
// component: GrantEditorWizardComponent,
|
||||
// data: {
|
||||
// breadcrumb: true
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// path: 'dmp',
|
||||
// component: DmpEditorWizardComponent,
|
||||
// data: {
|
||||
// breadcrumb: true
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// path: 'dataset',
|
||||
// component: DatasetEditorWizardComponent,
|
||||
// data: {
|
||||
// breadcrumb: true
|
||||
// },
|
||||
// }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class QuickWizardRoutingModule { }
|
|
@ -41,12 +41,15 @@
|
|||
"PUBLISH-ITEM": "Publish this item?",
|
||||
"ADD-DATASET": "Do you want to continue by adding a Dataset Description to your DMP? You can always add more Dataset Descriptions using \"Add Dataset Description (Wizard)\" menu.",
|
||||
"ZENODO-DOI": "Would you like to create digital object identifier (DOI) for the DMP?",
|
||||
"LEAVE-PAGE": "If you leave, your changes will be lost.",
|
||||
"LEAVE-WARNING": "You have unsaved changes!",
|
||||
"ACTIONS": {
|
||||
"CONFIRM": "Yes",
|
||||
"NO": "No",
|
||||
"DELETE": "Delete",
|
||||
"REMOVE": "Remove",
|
||||
"CANCEL": "Cancel"
|
||||
"CANCEL": "Cancel",
|
||||
"LEAVE": "Leave"
|
||||
}
|
||||
},
|
||||
"ACTIONS": {
|
||||
|
|
Loading…
Reference in New Issue