diff --git a/core/app/src/store/record/record.manager.ts b/core/app/src/store/record/record.manager.ts index 95e067d61..bf59e32a7 100644 --- a/core/app/src/store/record/record.manager.ts +++ b/core/app/src/store/record/record.manager.ts @@ -143,6 +143,19 @@ export class RecordManager { return deepClone(this.internalState); } + /** + * Is staging record dirty + * + * @returns {object} Record + */ + isDirty(): boolean { + if (!this.stagingState || !this.stagingState.formGroup) { + return false; + } + + return this.stagingState.formGroup.dirty; + } + /** * Get record cached Observable or call the backend * diff --git a/core/app/views/record/actions/cancel/record-cancel.action.ts b/core/app/views/record/actions/cancel/record-cancel.action.ts index 3967e9487..a29c3c374 100644 --- a/core/app/views/record/actions/cancel/record-cancel.action.ts +++ b/core/app/views/record/actions/cancel/record-cancel.action.ts @@ -1,6 +1,9 @@ import {Injectable} from '@angular/core'; import {RecordActionData, RecordActionHandler} from '@views/record/actions/record.action'; import {ViewMode} from '@app-common/views/view.model'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {MessageModalComponent} from '@components/modal/components/message-modal/message-modal.component'; +import {ModalButtonInterface} from '@app-common/components/modal/modal.model'; @Injectable({ providedIn: 'root' @@ -10,16 +13,47 @@ export class RecordCancelAction extends RecordActionHandler { key = 'cancel'; modes = ['edit' as ViewMode]; - constructor() { + constructor(private modalService: NgbModal) { super(); } run(data: RecordActionData): void { - data.store.recordManager.resetStaging(); - data.store.setMode('detail' as ViewMode); + + if (data.store.recordManager.isDirty()) { + this.showConfirmationModal(data); + return; + } + + this.cancel(data); } shouldDisplay(): boolean { return true; } + + protected cancel(data: RecordActionData): void { + data.store.recordManager.resetStaging(); + data.store.setMode('detail' as ViewMode); + } + + protected showConfirmationModal(data: RecordActionData): void { + const modal = this.modalService.open(MessageModalComponent); + + modal.componentInstance.textKey = 'WARN_UNSAVED_CHANGES'; + modal.componentInstance.buttons = [ + { + labelKey: 'LBL_CANCEL', + klass: ['btn-secondary'], + onClick: activeModal => activeModal.dismiss() + } as ModalButtonInterface, + { + labelKey: 'LBL_OK', + klass: ['btn-main'], + onClick: activeModal => { + this.cancel(data); + activeModal.close(); + } + } as ModalButtonInterface, + ]; + } } diff --git a/core/app/views/record/actions/record-action-manager.service.spec.mock.ts b/core/app/views/record/actions/record-action-manager.service.spec.mock.ts index 2c20c3071..290619ca3 100644 --- a/core/app/views/record/actions/record-action-manager.service.spec.mock.ts +++ b/core/app/views/record/actions/record-action-manager.service.spec.mock.ts @@ -7,20 +7,40 @@ import {RecordActionManager} from '@views/record/actions/record-action-manager.s import {moduleNameMapperMock} from '@services/navigation/module-name-mapper/module-name-mapper.service.spec.mock'; import {RecordSaveAction} from '@views/record/actions/save/record-save.action'; import {messageServiceMock} from '@services/message/message.service.spec.mock'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {NgbModalRef} from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'; const mockRouter = { - navigate: ( - // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars - commands: any[], - // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars - extras?: NavigationExtras - ) => null + navigate: (commands: any[], extras?: NavigationExtras) => { + if (!extras || !commands) { + return null; + } + + return null; + } } as Router; +export class MockModal extends NgbModal { + + constructor() { + super(null, null, null, null); + } + + open(): NgbModalRef { + return { + componentInstance: { + textKey: '', + buttons: [] + } + } as NgbModalRef; + } +} + + export const recordActionsManagerMock = new RecordActionManager( new RecordEditAction(), new RecordCreateAction(moduleNameMapperMock, mockRouter), new RecordToggleWidgetsAction(), - new RecordCancelAction(), + new RecordCancelAction(new MockModal()), new RecordSaveAction(messageServiceMock) );