<eg-string #createString i18n-text text="New Provider Added"></eg-string>
<eg-string #createErrString i18n-text text="Failed to Create New Provider"></eg-string>
+<eg-confirm-dialog #leaveConfirm
+ i18n-dialogTitle i18n-dialogBody
+ dialogTitle="Unsaved Changes Warning"
+ dialogBody="There are unsaved changes. Are you sure you want to leave?">
+</eg-confirm-dialog>
+
<div><div class="row">
<div class="col">
(click)="setDefaultTab()" i18n>Set Default View</button>
</div>
</div>
- <eg-provider-holdings></eg-provider-holdings>
+ <eg-provider-holdings #providerHoldings></eg-provider-holdings>
</ng-template>
</ngb-tab>
<ngb-tab title="EDI" i18n-title id="edi_accounts" [disabled]="!id || !this.providerRecord.currentProvider.canAdmin">
import {Component, OnInit, AfterViewInit, ViewChild, ChangeDetectorRef, OnDestroy} from '@angular/core';
import {filter, takeUntil} from 'rxjs/operators';
-import {Subject} from 'rxjs';
+import {Subject, Observable, of} from 'rxjs';
import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
import {Router, ActivatedRoute, ParamMap, RouterEvent, NavigationEnd} from '@angular/router';
import {StaffCommonModule} from '@eg/staff/common.module';
import {PcrudService} from '@eg/core/pcrud.service';
import {AcqProviderSummaryPaneComponent} from './summary-pane.component';
import {ProviderDetailsComponent} from './provider-details.component';
+import {ProviderHoldingsComponent} from './provider-holdings.component';
import {ProviderResultsComponent} from './provider-results.component';
import {ProviderRecordService} from './provider-record.service';
import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
import {ToastService} from '@eg/share/toast/toast.service';
import {AuthService} from '@eg/core/auth.service';
import {StoreService} from '@eg/core/store.service';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
@Component({
templateUrl: './acq-provider.component.html'
@ViewChild('acqSearchProviderSummary', { static: true }) providerSummaryPane: AcqProviderSummaryPaneComponent;
@ViewChild('acqProviderResults', { static: true }) acqProviderResults: ProviderResultsComponent;
@ViewChild('providerDetails', { static: false }) providerDetails: ProviderDetailsComponent;
+ @ViewChild('providerHoldings', { static: false }) providerHoldings: ProviderHoldingsComponent;
@ViewChild('createDialog', { static: true }) createDialog: FmRecordEditorComponent;
@ViewChild('createString', { static: false }) createString: StringComponent;
@ViewChild('createErrString', { static: false }) createErrString: StringComponent;
+ @ViewChild('leaveConfirm', { static: true }) leaveConfirm: ConfirmDialogComponent;
onTabChange: ($event: NgbTabChangeEvent) => void;
previousUrl: string = null;
public destroyed = new Subject<any>();
+ _alreadyDeactivated = false;
constructor(
private router: Router,
}
this.onTabChange = ($event) => {
- if (this.validTabTypes.includes($event.nextId)) {
- this.activeTab = $event.nextId;
- const id = this.route.snapshot.paramMap.get('id');
- this.router.navigate(['/staff', 'acq', 'provider', this.id, $event.nextId]);
- }
+ $event.preventDefault();
+ this.canDeactivate().subscribe(canLeave => {
+ if (!canLeave) { return; }
+ this._alreadyDeactivated = true; // don't trigger again on the route change
+ if (this.validTabTypes.includes($event.nextId)) {
+ this.activeTab = $event.nextId;
+ const id = this.route.snapshot.paramMap.get('id');
+ this.router.navigate(['/staff', 'acq', 'provider', this.id, $event.nextId]);
+ }
+ });
};
this.onDesireSummarize = ($event, updateSummaryOnly = false) => {
}
);
}
+
+ canDeactivate(): Observable<boolean> {
+ if (this._alreadyDeactivated) {
+ // one freebie
+ this._alreadyDeactivated = false;
+ return of(true);
+ }
+ if ((this.providerHoldings && this.providerHoldings.isDirty()) ||
+ (this.providerDetails && this.providerDetails.isDirty())) {
+ return this.leaveConfirm.open();
+ } else {
+ return of(true);
+ }
+ }
}
@ViewChild('updateFailedString', { static: false }) updateFailedString: StringComponent;
@ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent;
@ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent;
+ @ViewChild('editDialog', { static: false}) editDialog: FmRecordEditorComponent;
provider: IdlObject;
return this.providerRecord.currentProviderRecord().canAdmin ? 'update' : 'view';
}
+ isDirty(): boolean {
+ return (this.editDialog) ? this.editDialog.isDirty() : false;
+ }
}
import {Component, OnInit, AfterViewInit, OnDestroy, Input, ViewChild} from '@angular/core';
+import {NgForm} from '@angular/forms';
import {empty, throwError, Observable, from, Subscription} from 'rxjs';
import {map} from 'rxjs/operators';
import {Router, ActivatedRoute, ParamMap} from '@angular/router';
@ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent;
@ViewChild('successTagString', { static: true }) successTagString: StringComponent;
@ViewChild('updateFailedTagString', { static: false }) updateFailedTagString: StringComponent;
+ @ViewChild('holdingTagForm', { static: false}) holdingTagForm: NgForm;
cellTextGenerator: GridCellTextGenerator;
provider: IdlObject;
}
ngAfterViewInit() {
- console.log('this.providerRecord',this.providerRecord);
+ if (this.providerRecord.current()) {
+ // sometimes needs to force a refresh in case we updated that tag,
+ // navigated away (and confirmed that we wanted to abandon the change),
+ // then navigated back
+ this.providerRecord.current()['_holding_tag'] = this.providerRecord.current().holding_tag();
+ }
}
}
);
}
+
+ isDirty() : boolean {
+ return (this.providerRecord.current()['_holding_tag'] == this.providerRecord.current().holding_tag()) ? false :
+ (this.holdingTagForm && this.holdingTagForm.dirty) ? this.holdingTagForm.dirty : false;
+ }
}
{}
).pipe(map(acqpro => {
const provider = new ProviderRecord(acqpro);
+ // make a copy of holding_tag for use by the holdings definitions tab
+ acqpro['_holding_tag'] = acqpro.holding_tag();
acqpro.edi_accounts().forEach(acct => {
acct['_is_default'] = false;
if (acqpro.edi_default()) {
import {Injectable} from '@angular/core';
+import {Observable} from 'rxjs';
import {Router, Resolve, RouterStateSnapshot,
- ActivatedRouteSnapshot} from '@angular/router';
+ ActivatedRouteSnapshot, CanDeactivate} from '@angular/router';
import {ProviderRecordService} from './provider-record.service';
@Injectable()
}
+// following example of https://www.concretepage.com/angular-2/angular-candeactivate-guard-example
+export interface DeactivationGuarded {
+ canDeactivate(): Observable<boolean> | Promise<boolean> | boolean;
+}
+
+@Injectable()
+export class CanLeaveAcqProviderGuard implements CanDeactivate<DeactivationGuarded> {
+ canDeactivate(component: DeactivationGuarded): Observable<boolean> | Promise<boolean> | boolean {
+ return component.canDeactivate ? component.canDeactivate() : true;
+ }
+}
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {AcqProviderComponent} from './acq-provider.component';
-import {ProviderResolver} from './resolver.service';
+import {ProviderResolver, CanLeaveAcqProviderGuard} from './resolver.service';
const routes: Routes = [
{ path: '',
{ path: ':id/:tab',
component: AcqProviderComponent,
resolve: { providerResolver : ProviderResolver },
+ canDeactivate: [CanLeaveAcqProviderGuard],
runGuardsAndResolvers: 'always'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
- providers: [ProviderResolver]
+ providers: [ProviderResolver, CanLeaveAcqProviderGuard]
})
export class AcqProviderRoutingModule {}