[open-ils-commits] [GIT] Evergreen ILS branch master updated. e4cd70354858d98c05d435fa9a273a07d06152e1

Evergreen Git git at git.evergreen-ils.org
Thu Jun 20 10:29:52 EDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  e4cd70354858d98c05d435fa9a273a07d06152e1 (commit)
       via  91c438ce94183d72eb758b6d9307b9dda5979120 (commit)
       via  efc79c1e363be74e88939617760dd618c95b6b59 (commit)
       via  c707fad01d3ea57e998a369247eee2e16c9332cb (commit)
       via  2f8ada257adcb2eb54ecb3517eff9381fa902f25 (commit)
      from  f313a5d7d5855d09973a3463ac0bf5d6d3423936 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit e4cd70354858d98c05d435fa9a273a07d06152e1
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Jun 19 16:41:26 2019 -0400

    LP1823041 Confirm dialog returns true/false repairs
    
    The new Observable-driven confirm dialogs return true or false depending
    on the user response (or nothing if dismissed), so the calling code needs
    to verify the user confirmed the request before continuing.
    
    Removed an unused confirm dialog import for clarity.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
index 0366d73989..20938c459d 100644
--- a/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
@@ -109,27 +109,27 @@ export class OrgUnitTypeComponent implements OnInit {
     }
 
     remove() {
-        this.delConfirm.open().subscribe(
-            ok => {
-                this.pcrud.remove(this.selected.callerData.aout)
-                .subscribe(
-                    ok2 => {},
-                    err => {
-                        this.errorString.current()
-                          .then(str => this.toast.danger(str));
-                    },
-                    ()  => {
-                        // Avoid updating until we know the entire
-                        // pcrud action/transaction completed.
-                        this.loadAoutTree(); // since the tree is never going to
-                                             // be large, just reload the whole
-                                             // thing
-                        this.selected = null;
-                        this.postUpdate(this.editString);
-                    }
-                );
-            }
-        );
+        this.delConfirm.open().subscribe(confirmed => {
+            if (!confirmed) { return; }
+
+            this.pcrud.remove(this.selected.callerData.aout)
+            .subscribe(
+                ok2 => {},
+                err => {
+                    this.errorString.current()
+                      .then(str => this.toast.danger(str));
+                },
+                ()  => {
+                    // Avoid updating until we know the entire
+                    // pcrud action/transaction completed.
+                    this.loadAoutTree(); // since the tree is never going to
+                                         // be large, just reload the whole
+                                         // thing
+                    this.selected = null;
+                    this.postUpdate(this.editString);
+                }
+            );
+        });
     }
 
     addChild() {
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
index 1ba570d407..bf6e682428 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
@@ -72,28 +72,28 @@ export class ConjoinedComponent implements OnInit {
         this.idsToUnlink = rows.map(r => r.target_copy().id());
         if (this.idsToUnlink.length === 0) { return; }
 
-        try { // rejects on dismiss, which results in an Error
-            // TODO this will change with LP #1823041
-            await this.confirmUnlink.open({size: 'sm'});
-        } catch (dismissed) { return; }
-
-        const maps = [];
-        this.pcrud.search('bpbcm',
-            {target_copy: this.idsToUnlink, peer_record: this.recordId})
-        .subscribe(
-            map => maps.push(map),
-            err => {},
-            () => {
-                this.pcrud.remove(maps).subscribe(
-                    ok => console.debug('deleted map ', ok),
-                    err => console.error(err),
-                    ()  => {
-                        this.idsToUnlink = [];
-                        this.grid.reload();
-                    }
-                );
-            }
-        );
+        this.confirmUnlink.open({size: 'sm'}).subscribe(confirmed => {
+
+            if (!confirmed) { return; }
+
+            const maps = [];
+            this.pcrud.search('bpbcm',
+                {target_copy: this.idsToUnlink, peer_record: this.recordId})
+            .subscribe(
+                map => maps.push(map),
+                err => {},
+                () => {
+                    this.pcrud.remove(maps).subscribe(
+                        ok => console.debug('deleted map ', ok),
+                        err => console.error(err),
+                        ()  => {
+                            this.idsToUnlink = [];
+                            this.grid.reload();
+                        }
+                    );
+                }
+            );
+        });
     }
 
     openConjoinedDialog() {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
index 6d96a91ea7..16fd66cff7 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
@@ -12,7 +12,6 @@ import {StringComponent} from '@eg/share/string/string.component';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
-import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 
 /**
  * Dialog for managing copy alerts.
@@ -52,8 +51,6 @@ export class CopyAlertsDialogComponent
 
     @ViewChild('successMsg') private successMsg: StringComponent;
     @ViewChild('errorMsg') private errorMsg: StringComponent;
-    @ViewChild('confirmDeleteDialog')
-        private confirmDeleteDialog: ConfirmDialogComponent;
 
     constructor(
         private modal: NgbModal, // required for passing to parent

commit 91c438ce94183d72eb758b6d9307b9dda5979120
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Jun 19 16:25:51 2019 -0400

    LP1823041 Observable dialogs repairs and cleanup
    
    Fixes a few instances where dialog.open() calls did not return
    Observables.
    
    Replace a number of calls to the now deprecated dialog.dismiss() with
    calls to dialog.close().
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/staff/share/booking/make-bookable-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/booking/make-bookable-dialog.component.html
index 25ad596575..aa7793581a 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/booking/make-bookable-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/booking/make-bookable-dialog.component.html
@@ -11,7 +11,7 @@
         <span i18n>Make Items Bookable</span>
       </h4>
       <button type="button" class="close" 
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -36,7 +36,7 @@
     <div class="modal-footer">
       <ng-container>
         <button type="button" class="btn btn-warning" 
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <ng-container *ngIf="!updateComplete">
           <button type="button" class="btn btn-success" 
             (click)="makeBookable()" i18n>Make Bookable</button>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/conjoined-items-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/conjoined-items-dialog.component.html
index 9801c3ee77..33b433fe45 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/conjoined-items-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/conjoined-items-dialog.component.html
@@ -11,7 +11,7 @@
         <span i18n>Attach/Modify {{copyIds.length}} Conjoined Item(s)</span>
       </h4>
       <button type="button" class="close" 
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -31,7 +31,7 @@
     <div class="modal-footer">
       <ng-container>
         <button type="button" class="btn btn-warning" 
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success" 
           (click)="linkCopies()" [disabled]="!peerType" i18n>
           Attach/Modify
@@ -39,4 +39,4 @@
       </ng-container>
     </div>
   </ng-template>
-  
\ No newline at end of file
+  
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.html
index 4b3c1caab1..039d776f13 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.html
@@ -13,7 +13,7 @@
       <span i18n></span>
     </h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -100,7 +100,7 @@
   </div>
   <div class="modal-footer">
     <button type="button" class="btn btn-secondary" 
-      (click)="dismiss('canceled')" i18n>Close</button>
+      (click)="close()" i18n>Close</button>
     <ng-container *ngIf="mode == 'manage'">
       <button class="btn btn-success mr-2" 
         (click)="applyChanges()" i18n>Apply Changes</button>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
index 450fc348b0..6d96a91ea7 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
@@ -1,5 +1,6 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
-import {Observable, throwError} from 'rxjs';
+import {Observable, throwError, from} from 'rxjs';
+import {switchMap} from 'rxjs/operators';
 import {NetService} from '@eg/core/net.service';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
@@ -94,15 +95,15 @@ export class CopyAlertsDialogComponent
             }
         }
 
-        this.getAlertTypes()
-        .then(() => this.getCopies())
-        .then(() => {
-            if (this.mode === 'manage') {
-                this.getCopyAlerts()
-                .then(() => super.open(args) );
-            }
-            return super.open(args);
-        });
+        // Observerify data loading
+        const obs = from(
+            this.getAlertTypes()
+            .then(_ => this.getCopies())
+            .then(_ => this.mode === 'manage' ? this.getCopyAlerts() : null)
+        );
+
+        // Return open() observable to caller
+        return obs.pipe(switchMap(_ => super.open(args)));
     }
 
     getAlertTypes(): Promise<any> {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.html
index 9a07de77ff..30b0f2c434 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.html
@@ -12,7 +12,7 @@
         <span i18n>Delete Holdings</span>
       </h4>
       <button type="button" class="close" 
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -22,7 +22,7 @@
     <div class="modal-footer">
       <ng-container>
         <button type="button" class="btn btn-warning" 
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success" 
           (click)="deleteHoldings()" i18n>
           Delete Holdings
@@ -30,4 +30,4 @@
       </ng-container>
     </div>
   </ng-template>
-  
\ No newline at end of file
+  
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.html
index ddcf6b1134..0c53c9c5af 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.html
@@ -7,7 +7,7 @@
       <span i18n>Mark Item Damaged</span>
     </h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close(false)">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -90,13 +90,13 @@
   <div class="modal-footer">
     <ng-container *ngIf="!chargeResponse">
       <button type="button" class="btn btn-warning" 
-        (click)="dismiss('canceled')" i18n>Cancel</button>
+        (click)="close(false)" i18n>Cancel</button>
       <button type="button" class="btn btn-success" 
         (click)="markDamaged()" i18n>Mark Damaged</button>
     </ng-container>
     <ng-container *ngIf="chargeResponse">
       <button type="button" class="btn btn-warning" 
-        (click)="dismiss('canceled')" i18n>Cancel</button>
+        (click)="close(false)" i18n>Cancel</button>
       <button class="btn btn-info mr-2" 
         (click)="amountChangeRequested = true" i18n>Change Amount</button>
       <button class="btn btn-secondary mr-2" 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
index 8a1c7130f1..346b3f0500 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
@@ -1,5 +1,6 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
-import {Observable, throwError} from 'rxjs';
+import {Observable, throwError, from} from 'rxjs';
+import {switchMap} from 'rxjs/operators';
 import {NetService} from '@eg/core/net.service';
 import {IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
@@ -70,9 +71,13 @@ export class MarkDamagedDialogComponent
             return throwError('copy ID required');
         }
 
-        this.getBillingTypes()
-        .then(() => { this.getData(); })
-        .then(() => super.open(args));
+        // Map data-loading promises to an observable
+        const obs = from(
+            this.getBillingTypes().then(_ => this.getData()));
+
+        // Fire data loading observable and replace results with
+        // dialog opener observable.
+        return obs.pipe(switchMap(_ => super.open(args)));
     }
 
     // Fetch-cache billing types
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-missing-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-missing-dialog.component.html
index 5e85a861a9..ea6b7d709c 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-missing-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-missing-dialog.component.html
@@ -11,7 +11,7 @@
         <span i18n>Mark Item Missing</span>
       </h4>
       <button type="button" class="close" 
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -35,10 +35,10 @@
     <div class="modal-footer">
       <ng-container *ngIf="!chargeResponse">
         <button type="button" class="btn btn-warning" 
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success" 
           (click)="markItemsMissing()" i18n>Mark Missing</button>
       </ng-container>
     </div>
   </ng-template>
-  
\ No newline at end of file
+  
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.html
index 562681bcd9..8bca301cbd 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.html
@@ -11,7 +11,7 @@
         <span i18n>Replace Item Barcode</span>
       </h4>
       <button type="button" class="close" 
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -39,7 +39,7 @@
     <div class="modal-footer">
       <ng-container>
         <button type="button" class="btn btn-warning" 
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success" 
           (click)="replaceOneBarcode()" [disabled]="!newBarcode" i18n>
           Replace Barcode
@@ -47,4 +47,4 @@
       </ng-container>
     </div>
   </ng-template>
-  
\ No newline at end of file
+  
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
index 2d18eb9bb3..2b85d38931 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
@@ -1,6 +1,6 @@
 import {Component, OnInit, Input, ViewChild, Renderer2} from '@angular/core';
 import {Observable, throwError} from 'rxjs';
-import {flatMap, map, tap} from 'rxjs/operators';
+import {switchMap, map, tap} from 'rxjs/operators';
 import {IdlObject} from '@eg/core/idl.service';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
@@ -59,10 +59,10 @@ export class ReplaceBarcodeDialogComponent
         this.numFailed = 0;
 
         return this.getNextCopy()
-        .pipe(flatMap(() => {
-            return super.open(args)
-            .pipe(tap(() => {this.renderer.selectRootElement('#new-barcode-input').focus(); }));
-        }));
+        .pipe(switchMap(() => super.open(args)))
+        .pipe(tap(() =>
+            this.renderer.selectRootElement('#new-barcode-input').focus())
+        );
     }
 
     getNextCopy(): Observable<any> {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.html
index d7417fa646..a2d70cd9fa 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.html
@@ -9,7 +9,7 @@
         <span i18n>Cancel Hold</span>
       </h4>
       <button type="button" class="close"
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -52,9 +52,9 @@
     <div class="modal-footer">
       <ng-container *ngIf="!chargeResponse">
         <button type="button" class="btn btn-warning"
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success"
           (click)="cancelBatch()" i18n>Cancel Hold</button>
       </ng-container>
     </div>
-  </ng-template>
\ No newline at end of file
+  </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.html
index ac07dd6f35..1a8cbc320a 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.html
@@ -7,7 +7,7 @@
         <h4 class="modal-title">Batch Modify {{holdIds.length}} Holds</h4>
       </ng-container>
       <button type="button" class="close"
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -15,4 +15,4 @@
       <eg-hold-manage [holdIds]="holdIds" (onComplete)="onComplete($event)">
       </eg-hold-manage>
     </div>
-  </ng-template>
\ No newline at end of file
+  </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.html
index 37d349dd80..b24a63e62e 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.html
@@ -9,7 +9,7 @@
         <span i18n>Retarget Hold</span>
       </h4>
       <button type="button" class="close"
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -33,9 +33,9 @@
     <div class="modal-footer">
       <ng-container *ngIf="!chargeResponse">
         <button type="button" class="btn btn-warning"
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success"
           (click)="retargetBatch()" i18n>Retarget</button>
       </ng-container>
     </div>
-  </ng-template>
\ No newline at end of file
+  </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.html
index 80728caf8b..9046836a14 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.html
@@ -11,7 +11,7 @@
         <span i18n>Transfer Hold(s) To Marked Target</span>
       </h4>
       <button type="button" class="close"
-        i18n-aria-label aria-label="Close" (click)="dismiss('cross_click')">
+        i18n-aria-label aria-label="Close" (click)="close()">
         <span aria-hidden="true">×</span>
       </button>
     </div>
@@ -35,9 +35,9 @@
     <div class="modal-footer">
       <ng-container *ngIf="!chargeResponse">
         <button type="button" class="btn btn-warning"
-          (click)="dismiss('canceled')" i18n>Cancel</button>
+          (click)="close()" i18n>Cancel</button>
         <button type="button" class="btn btn-success"
           (click)="transferBatch()" i18n>Transfer</button>
       </ng-container>
     </div>
-  </ng-template>
\ No newline at end of file
+  </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
index 58b8200083..796aa107a6 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
@@ -53,8 +53,9 @@ export class HoldTransferDialogComponent
 
         if (!this.transferTarget) {
             this.targetNeeded.current()
-            .then((msg) => this.toast.warning(msg))
-            .then(() => throwError('Transfer Target Required'));
+            .then((msg) => this.toast.warning(msg));
+
+            return throwError('Transfer Target Required');
         }
 
         return super.open(args);

commit efc79c1e363be74e88939617760dd618c95b6b59
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Jun 19 16:14:39 2019 -0400

    LP1823041 Remove unintentially merged code blocks
    
    A chunk of Angular code which was removed before merging this LP was
    added back during the rebase/merge process.  This removes the errant
    code.
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
index 0930d5c1c4..a1dc1c61aa 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
@@ -171,91 +171,6 @@ export class AdminPageComponent implements OnInit {
         this.grid.onRowActivate.subscribe(
             (idlThing: IdlObject) => this.showEditDialog(idlThing)
         );
-
-        this.editSelected = (idlThings: IdlObject[]) => {
-
-            // Edit each IDL thing one at a time
-            const editOneThing = (thing: IdlObject) => {
-                if (!thing) { return; }
-
-                this.showEditDialog(thing).then(
-                    () => editOneThing(idlThings.shift()));
-            };
-
-            editOneThing(idlThings.shift());
-        };
-
-        this.createNew = () => {
-            this.editDialog.mode = 'create';
-            // We reuse the same editor for all actions.  Be sure
-            // create action does not try to modify an existing record.
-            this.editDialog.recId = null;
-            this.editDialog.record = null;
-            this.editDialog.open({size: this.dialogSize}).subscribe(
-                result => {
-                    this.createString.current()
-                        .then(str => this.toast.success(str));
-                    this.grid.reload();
-                },
-                error => {
-                    this.createErrString.current()
-                        .then(str => this.toast.danger(str));
-                }
-            );
-        };
-
-        this.deleteSelected = (idlThings: IdlObject[]) => {
-            idlThings.forEach(idlThing => idlThing.isdeleted(true));
-            this.pcrud.autoApply(idlThings).subscribe(
-                val => console.debug('deleted: ' + val),
-                err => {},
-                ()  => this.grid.reload()
-            );
-        };
-
-        // Open the field translation dialog.
-        // Link the next/previous actions to cycle through each translatable
-        // field on each row.
-        this.translate = () => {
-            this.translateRowIdx = 0;
-            this.translateFieldIdx = 0;
-            this.translator.fieldName = this.translatableFields[this.translateFieldIdx];
-            this.translator.idlObject = this.dataSource.data[this.translateRowIdx];
-
-            this.translator.nextString = () => {
-
-                if (this.translateFieldIdx < this.translatableFields.length - 1) {
-                    this.translateFieldIdx++;
-
-                } else if (this.translateRowIdx < this.dataSource.data.length - 1) {
-                    this.translateRowIdx++;
-                    this.translateFieldIdx = 0;
-                }
-
-                this.translator.idlObject =
-                    this.dataSource.data[this.translateRowIdx];
-                this.translator.fieldName =
-                    this.translatableFields[this.translateFieldIdx];
-            };
-
-            this.translator.prevString = () => {
-
-                if (this.translateFieldIdx > 0) {
-                    this.translateFieldIdx--;
-
-                } else if (this.translateRowIdx > 0) {
-                    this.translateRowIdx--;
-                    this.translateFieldIdx = 0;
-                }
-
-                this.translator.idlObject =
-                    this.dataSource.data[this.translateRowIdx];
-                this.translator.fieldName =
-                    this.translatableFields[this.translateFieldIdx];
-            };
-
-            this.translator.open({size: 'lg'});
-        };
     }
 
     checkCreatePerms() {

commit c707fad01d3ea57e998a369247eee2e16c9332cb
Author: Jane Sandberg <sandbej at linnbenton.edu>
Date:   Wed Jun 19 10:17:40 2019 -0700

    LP1823041: Converting new dialogs to observables
    
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>
    Signed-off-by: Bill Erickson <berickxx at gmail.com>

diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
index e283cc2106..f25839b1f1 100644
--- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
+++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
@@ -520,14 +520,12 @@ export class FmRecordEditorComponent
         this.translator.fieldName = field;
         this.translator.idlObject = this.record;
 
-        // TODO: will need to change once LP1823041 is merged
-        this.translator.open().then(
+        this.translator.open().subscribe(
             newValue => {
                 if (newValue) {
                     this.record[field](newValue);
                 }
-            },
-            () => {} // avoid console error
+            }
         );
     }
 }
diff --git a/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
index 77d007bcd0..0366d73989 100644
--- a/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/admin/server/org-unit-type.component.ts
@@ -91,7 +91,7 @@ export class OrgUnitTypeComponent implements OnInit {
         this.editDialog.mode = 'update';
         this.editDialog.setRecord(this.selected.callerData.aout);
 
-        this.editDialog.open().then(
+        this.editDialog.open().subscribe(
             success => {
                 this.postUpdate(this.editString);
                 this.loadAoutTree(); // since the tree is never going to
@@ -109,7 +109,7 @@ export class OrgUnitTypeComponent implements OnInit {
     }
 
     remove() {
-        this.delConfirm.open().then(
+        this.delConfirm.open().subscribe(
             ok => {
                 this.pcrud.remove(this.selected.callerData.aout)
                 .subscribe(
@@ -128,8 +128,7 @@ export class OrgUnitTypeComponent implements OnInit {
                         this.postUpdate(this.editString);
                     }
                 );
-            },
-            notConfirmed => {}
+            }
         );
     }
 
@@ -144,7 +143,7 @@ export class OrgUnitTypeComponent implements OnInit {
         this.editDialog.setRecord(newType);
         this.editDialog.mode = 'create';
 
-        this.editDialog.open().then(
+        this.editDialog.open().subscribe(
             result => { // aout object
 
                 // Add our new node to the tree
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts
index da3f793625..c42b7ddc75 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/basket-actions.component.ts
@@ -97,10 +97,7 @@ export class BasketActionsComponent implements OnInit {
                 this.basket.getRecordIds().then(ids => {
                     this.addToBucketDialog.bucketClass = 'biblio';
                     this.addToBucketDialog.itemIds = ids;
-                    this.addToBucketDialog.open({size: 'lg'}).then(
-                        ok => {},
-                        dismissed => {}
-                    );
+                    this.addToBucketDialog.open({size: 'lg'});
                 });
                 break;
 
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
index b4d6274973..1ba570d407 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/conjoined.component.ts
@@ -97,13 +97,12 @@ export class ConjoinedComponent implements OnInit {
     }
 
     openConjoinedDialog() {
-        this.conjoinedDialog.open({size: 'sm'}).then(
+        this.conjoinedDialog.open({size: 'sm'}).subscribe(
             modified => {
                 if (modified) {
                     this.grid.reload();
                 }
-            },
-            notOk => {}
+            }
         );
     }
 }
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
index 7ffa692be2..a89444b868 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
@@ -609,7 +609,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
             }
 
             this.markDamagedDialog.copyId = ids.pop();
-            return this.markDamagedDialog.open({size: 'lg'}).then(
+            return this.markDamagedDialog.open({size: 'lg'}).subscribe(
                 ok => {
                     if (ok) { rowsModified = true; }
                     return markNext(ids);
@@ -629,7 +629,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
         const copyIds = this.selectedCopyIds(rows, 4 /* ignore missing */);
         if (copyIds.length > 0) {
             this.markMissingDialog.copyIds = copyIds;
-            this.markMissingDialog.open({}).then(
+            this.markMissingDialog.open({}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.refreshHoldings = true;
@@ -762,13 +762,12 @@ export class HoldingsMaintenanceComponent implements OnInit {
 
         this.copyAlertsDialog.copyIds = copyIds;
         this.copyAlertsDialog.mode = mode;
-        this.copyAlertsDialog.open({size: 'lg'}).then(
+        this.copyAlertsDialog.open({size: 'lg'}).subscribe(
             modified => {
                 if (modified) {
                     this.hardRefresh();
                 }
-            },
-            dismissed => {}
+            }
         );
     }
 
@@ -776,13 +775,12 @@ export class HoldingsMaintenanceComponent implements OnInit {
         const ids = this.selectedCopyIds(rows);
         if (ids.length === 0) { return; }
         this.replaceBarcode.copyIds = ids;
-        this.replaceBarcode.open({}).then(
+        this.replaceBarcode.open({}).subscribe(
             modified => {
                 if (modified) {
                     this.hardRefresh();
                 }
-            },
-            dismissed => {}
+            }
         );
     }
 
@@ -835,13 +833,12 @@ export class HoldingsMaintenanceComponent implements OnInit {
         // "both" mode.
         this.deleteVolcopy.forceDeleteCopies = mode === 'both';
         this.deleteVolcopy.volumes = Object.values(volHash);
-        this.deleteVolcopy.open({size: 'sm'}).then(
+        this.deleteVolcopy.open({size: 'sm'}).subscribe(
             modified => {
                 if (modified) {
                     this.hardRefresh();
                 }
-            },
-            dismissed => {}
+            }
         );
     }
 
@@ -857,11 +854,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
         if (copyIds.length > 0) {
             this.bucketDialog.bucketClass = 'copy';
             this.bucketDialog.itemIds = copyIds;
-            this.bucketDialog.open({size: 'lg'}).then(
-                // No need to reload the grid after adding items to buckets.
-                ok => {},
-                dismissed => {}
-            );
+            this.bucketDialog.open({size: 'lg'});
         }
     }
 
@@ -869,10 +862,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
         const copyIds = this.selectedCopyIds(rows);
         if (copyIds.length > 0) {
             this.conjoinedDialog.copyIds = copyIds;
-            this.conjoinedDialog.open({size: 'sm'}).then(
-                ok => {}, // No grid reload required
-                dismissed => {}
-            );
+            this.conjoinedDialog.open({size: 'sm'});
         }
     }
 
@@ -887,10 +877,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
         const copyIds = this.selectedCopyIds(rows);
         if (copyIds.length > 0) {
             this.makeBookableDialog.copyIds = copyIds;
-            this.makeBookableDialog.open({}).then(
-                modified => {}, // No refresh needed
-                dismissed => {}
-            );
+            this.makeBookableDialog.open({});
         }
     }
 }
diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
index 2faf8f9d1d..0930d5c1c4 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
@@ -395,7 +395,7 @@ export class AdminPageComponent implements OnInit {
         // create action does not try to modify an existing record.
         this.editDialog.recId = null;
         this.editDialog.record = null;
-        this.editDialog.open({size: this.dialogSize}).then(
+        this.editDialog.open({size: this.dialogSize}).subscribe(
             ok => {
                 this.createString.current()
                     .then(str => this.toast.success(str));
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
index 630126b238..450fc348b0 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/copy-alerts-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
@@ -73,14 +74,14 @@ export class CopyAlertsDialogComponent
      * Dialog promise resolves with true/false indicating whether
      * the mark-damanged action occured or was dismissed.
      */
-    async open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.copy = null;
         this.copies = [];
         this.newAlert = this.idl.create('aca');
         this.newAlert.create_staff(this.auth.user().id());
 
         if (this.copyIds.length === 0) {
-            return Promise.reject('copy ID required');
+            return throwError('copy ID required');
         }
 
         // In manage mode, we can only manage a single copy.
@@ -93,15 +94,18 @@ export class CopyAlertsDialogComponent
             }
         }
 
-        await this.getAlertTypes();
-        await this.getCopies();
-        if (this.mode === 'manage') {
-            await this.getCopyAlerts();
-        }
-        return super.open(args);
+        this.getAlertTypes()
+        .then(() => this.getCopies())
+        .then(() => {
+            if (this.mode === 'manage') {
+                this.getCopyAlerts()
+                .then(() => super.open(args) );
+            }
+            return super.open(args);
+        });
     }
 
-    async getAlertTypes(): Promise<any> {
+    getAlertTypes(): Promise<any> {
         if (this.alertTypes) {
             return Promise.resolve();
         }
@@ -114,7 +118,7 @@ export class CopyAlertsDialogComponent
         });
     }
 
-    async getCopies(): Promise<any> {
+    getCopies(): Promise<any> {
         return this.pcrud.search('acp', {id: this.copyIds}, {}, {atomic: true})
         .toPromise().then(copies => {
             this.copies = copies;
@@ -128,7 +132,7 @@ export class CopyAlertsDialogComponent
     // Copy alerts for the selected copies which have not been
     // acknowledged by staff and are within org unit range of
     // the alert type.
-    async getCopyAlerts(): Promise<any> {
+    getCopyAlerts(): Promise<any> {
         const copyIds = this.copies.map(c => c.id());
         const typeIds = this.alertTypes.map(a => a.id);
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.ts
index 57c613db06..dc86d9b437 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/delete-volcopy-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild, Renderer2} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
 import {IdlObject} from '@eg/core/idl.service';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
@@ -57,7 +58,7 @@ export class DeleteVolcopyDialogComponent
 
     ngOnInit() {}
 
-    async open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.numVols = 0;
         this.numCopies = 0;
         this.numSucceeded = 0;
@@ -82,7 +83,7 @@ export class DeleteVolcopyDialogComponent
 
         if (this.numVols === 0 && this.numCopies === 0) {
             console.debug('Volcopy delete called with no usable data');
-            return Promise.resolve(false);
+            return throwError(false);
         }
 
         return super.open(args);
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
index 70d7f8fa9a..8a1c7130f1 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/mark-damaged-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
@@ -62,20 +63,20 @@ export class MarkDamagedDialogComponent
      * Dialog promise resolves with true/false indicating whether
      * the mark-damanged action occured or was dismissed.
      */
-    async open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.reset();
 
         if (!this.copyId) {
-            return Promise.reject('copy ID required');
+            return throwError('copy ID required');
         }
 
-        await this.getBillingTypes();
-        await this.getData();
-        return super.open(args);
+        this.getBillingTypes()
+        .then(() => { this.getData(); })
+        .then(() => super.open(args));
     }
 
     // Fetch-cache billing types
-    async getBillingTypes(): Promise<any> {
+    getBillingTypes(): Promise<any> {
         if (this.billingTypes.length > 1) {
             return Promise.resolve();
         }
@@ -89,7 +90,7 @@ export class MarkDamagedDialogComponent
         });
     }
 
-    async getData(): Promise<any> {
+    getData(): Promise<any> {
         return this.pcrud.retrieve('acp', this.copyId,
             {flesh: 1, flesh_fields: {acp: ['call_number']}}).toPromise()
         .then(copy => {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
index 2cd67de8d1..2d18eb9bb3 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holdings/replace-barcode-dialog.component.ts
@@ -1,4 +1,6 @@
 import {Component, OnInit, Input, ViewChild, Renderer2} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
+import {flatMap, map, tap} from 'rxjs/operators';
 import {IdlObject} from '@eg/core/idl.service';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
@@ -51,24 +53,23 @@ export class ReplaceBarcodeDialogComponent
 
     ngOnInit() {}
 
-    async open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.ids = [].concat(this.copyIds);
         this.numSucceeded = 0;
         this.numFailed = 0;
 
-        await this.getNextCopy();
-        setTimeout(() =>
-            // Give the dialog a chance to render
-            this.renderer.selectRootElement('#new-barcode-input').focus()
-        );
-        return super.open(args);
+        return this.getNextCopy()
+        .pipe(flatMap(() => {
+            return super.open(args)
+            .pipe(tap(() => {this.renderer.selectRootElement('#new-barcode-input').focus(); }));
+        }));
     }
 
-    async getNextCopy(): Promise<any> {
+    getNextCopy(): Observable<any> {
 
         if (this.ids.length === 0) {
             this.close(this.numSucceeded > 0);
-            return Promise.resolve();
+            return throwError(false);
         }
 
         this.newBarcode = '';
@@ -76,7 +77,7 @@ export class ReplaceBarcodeDialogComponent
         const id = this.ids.pop();
 
         return this.pcrud.retrieve('acp', id)
-        .toPromise().then(c => this.copy = c);
+        .pipe(map(c => this.copy = c));
     }
 
     async replaceOneBarcode(): Promise<any> {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.ts
index 98af5143d3..d9c9295486 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/cancel-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
 import {ToastService} from '@eg/share/toast/toast.service';
@@ -48,7 +49,7 @@ export class HoldCancelDialogComponent
         // them to load regardless of whether the dialog is ever used.
     }
 
-    open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
 
         if (this.cancelReasons.length === 0) {
             this.pcrud.retrieveAll('ahrcc', {}, {atomic: true}).toPromise()
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts
index a95ed8572f..bdecd41afb 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/grid.component.ts
@@ -297,13 +297,12 @@ export class HoldsGridComponent implements OnInit {
         const holdIds = rows.map(r => r.id).filter(id => Boolean(id));
         if (holdIds.length > 0) {
             this.manageDialog.holdIds = holdIds;
-            this.manageDialog.open({size: 'lg'}).then(
+            this.manageDialog.open({size: 'lg'}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.holdsGrid.reload();
                     }
-                },
-                dismissed => {}
+                }
             );
         }
     }
@@ -312,13 +311,12 @@ export class HoldsGridComponent implements OnInit {
         const holdIds = rows.map(r => r.id).filter(id => Boolean(id));
         if (holdIds.length > 0) {
             this.transferDialog.holdIds = holdIds;
-            this.transferDialog.open({}).then(
+            this.transferDialog.open({}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.holdsGrid.reload();
                     }
-                },
-                dismissed => {}
+                }
             );
         }
     }
@@ -335,7 +333,7 @@ export class HoldsGridComponent implements OnInit {
             }
 
             this.markDamagedDialog.copyId = ids.pop();
-            return this.markDamagedDialog.open({size: 'lg'}).then(
+            return this.markDamagedDialog.open({size: 'lg'}).subscribe(
                 ok => {
                     if (ok) { rowsModified = true; }
                     return markNext(ids);
@@ -354,13 +352,12 @@ export class HoldsGridComponent implements OnInit {
         const copyIds = rows.map(r => r.cp_id).filter(id => Boolean(id));
         if (copyIds.length > 0) {
             this.markMissingDialog.copyIds = copyIds;
-            this.markMissingDialog.open({}).then(
+            this.markMissingDialog.open({}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.holdsGrid.reload();
                     }
-                },
-                dismissed => {} // avoid console errors
+                }
             );
         }
     }
@@ -369,13 +366,12 @@ export class HoldsGridComponent implements OnInit {
         const holdIds = rows.map(r => r.id).filter(id => Boolean(id));
         if (holdIds.length > 0) {
             this.retargetDialog.holdIds = holdIds;
-            this.retargetDialog.open({}).then(
+            this.retargetDialog.open({}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.holdsGrid.reload();
                     }
-                },
-                dismissed => {}
+                }
             );
         }
     }
@@ -384,13 +380,12 @@ export class HoldsGridComponent implements OnInit {
         const holdIds = rows.map(r => r.id).filter(id => Boolean(id));
         if (holdIds.length > 0) {
             this.cancelDialog.holdIds = holdIds;
-            this.cancelDialog.open({}).then(
+            this.cancelDialog.open({}).subscribe(
                 rowsModified => {
                     if (rowsModified) {
                         this.holdsGrid.reload();
                     }
-                },
-                dismissed => {}
+                }
             );
         }
     }
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.ts
index 93375c0eb7..1b539d16aa 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/manage-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input} from '@angular/core';
+import {Observable} from 'rxjs';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
 import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
 
@@ -21,7 +22,7 @@ export class HoldManageDialogComponent
         super(modal); // required for subclassing
     }
 
-    open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         return super.open(args);
     }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.ts
index feca64d92a..bb31a48602 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/retarget-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {EventService} from '@eg/core/event.service';
 import {ToastService} from '@eg/share/toast/toast.service';
@@ -39,7 +40,7 @@ export class HoldRetargetDialogComponent
 
     ngOnInit() {}
 
-    open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.holdIds = [].concat(this.holdIds); // array-ify ints
         return super.open(args);
     }
diff --git a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
index 5ce38ea02e..58b8200083 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/holds/transfer-dialog.component.ts
@@ -1,4 +1,5 @@
 import {Component, OnInit, Input, ViewChild} from '@angular/core';
+import {Observable, throwError} from 'rxjs';
 import {NetService} from '@eg/core/net.service';
 import {StoreService} from '@eg/core/store.service';
 import {EventService} from '@eg/core/event.service';
@@ -44,15 +45,16 @@ export class HoldTransferDialogComponent
 
     ngOnInit() {}
 
-    async open(args: NgbModalOptions): Promise<boolean> {
+    open(args: NgbModalOptions): Observable<boolean> {
         this.holdIds = [].concat(this.holdIds); // array-ify ints
 
         this.transferTarget =
             this.store.getLocalItem('eg.circ.hold.title_transfer_target');
 
         if (!this.transferTarget) {
-            this.toast.warning(await this.targetNeeded.current());
-            return Promise.reject('Transfer Target Required');
+            this.targetNeeded.current()
+            .then((msg) => this.toast.warning(msg))
+            .then(() => throwError('Transfer Target Required'));
         }
 
         return super.open(args);

commit 2f8ada257adcb2eb54ecb3517eff9381fa902f25
Author: Bill Erickson <berickxx at gmail.com>
Date:   Wed Apr 3 12:14:52 2019 -0400

    LP1823041 Angular dialogs return observables
    
    Dialog.open() now returns an observable to the caller.  This allows
    dialogs to pass 0 or more success events, error events, and close events
    each as descrete actions to the caller.
    
    Existing dialogs are updated to expect an Observable response to
    .open().
    
    Signed-off-by: Bill Erickson <berickxx at gmail.com>
    Signed-off-by: Jane Sandberg <sandbej at linnbenton.edu>

diff --git a/Open-ILS/src/eg2/src/app/share/accesskey/accesskey-info.component.html b/Open-ILS/src/eg2/src/app/share/accesskey/accesskey-info.component.html
index 82ed72a4b0..ae584cec40 100644
--- a/Open-ILS/src/eg2/src/app/share/accesskey/accesskey-info.component.html
+++ b/Open-ILS/src/eg2/src/app/share/accesskey/accesskey-info.component.html
@@ -2,8 +2,7 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title" i18n>Access Key Assignments</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/confirm.component.html b/Open-ILS/src/eg2/src/app/share/dialog/confirm.component.html
index 21766cac09..3db73cc8e0 100644
--- a/Open-ILS/src/eg2/src/app/share/dialog/confirm.component.html
+++ b/Open-ILS/src/eg2/src/app/share/dialog/confirm.component.html
@@ -2,16 +2,15 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title">{{dialogTitle}}</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
   <div class="modal-body"><p>{{dialogBody}}</p></div>
   <div class="modal-footer">
     <button type="button" class="btn btn-success" 
-      (click)="close('confirmed')" i18n>Confirm</button>
+      (click)="close(true)" i18n>Confirm</button>
     <button type="button" class="btn btn-warning" 
-      (click)="dismiss('canceled')" i18n>Cancel</button>
+      (click)="close(false)" i18n>Cancel</button>
   </div>
 </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/dialog.component.ts b/Open-ILS/src/eg2/src/app/share/dialog/dialog.component.ts
index e17fe8dcc7..79a5c8605d 100644
--- a/Open-ILS/src/eg2/src/app/share/dialog/dialog.component.ts
+++ b/Open-ILS/src/eg2/src/app/share/dialog/dialog.component.ts
@@ -1,19 +1,32 @@
 import {Component, Input, OnInit, ViewChild, TemplateRef, EventEmitter} from '@angular/core';
+import {Observable, Observer} from 'rxjs';
 import {NgbModal, NgbModalRef, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
 
 /**
  * Dialog base class.  Handles the ngbModal logic.
  * Sub-classed component templates must have a #dialogContent selector
  * at the root of the template (see ConfirmDialogComponent).
+ *
+ * Dialogs interact with the caller via Observable.
+ *
+ * dialog.open().subscribe(
+ *   value => handleValue(value),
+ *   error => handleError(error),
+ *   ()    => console.debug('dialog closed')
+ * );
+ *
+ * It is up to the dialog implementer to decide what values to
+ * pass to the caller via the dialog.respond(data) and/or
+ * dialog.close(data) methods.
+ *
+ * dialog.close(...) closes the modal window and completes the
+ * observable, unless an error was previously passed, in which
+ * case the observable is already complete.
+ *
+ * dialog.close() with no data closes the dialog without passing
+ * any values to the caller.
  */
 
-export interface DialogRejectionResponse {
-    // Did the user simply close the dialog without performing an action.
-    dismissed?: boolean;
-    // Relays error, etc. messages from the dialog handler to the caller.
-    message?: string;
-}
-
 @Component({
     selector: 'eg-dialog',
     template: '<ng-template></ng-template>'
@@ -32,6 +45,9 @@ export class DialogComponent implements OnInit {
     // called in the overridding method.
     onOpen$ = new EventEmitter<any>();
 
+    // How we relay responses to the caller.
+    observer: Observer<any>;
+
     // The modalRef allows direct control of the modal instance.
     private modalRef: NgbModalRef = null;
 
@@ -41,11 +57,11 @@ export class DialogComponent implements OnInit {
         this.onOpen$ = new EventEmitter<any>();
     }
 
-    async open(options?: NgbModalOptions): Promise<any> {
+    open(options?: NgbModalOptions): Observable<any> {
 
         if (this.modalRef !== null) {
-            console.warn('Dismissing existing dialog');
-            this.dismiss();
+            this.error('Dialog was replaced!');
+            this.finalize();
         }
 
         this.modalRef = this.modalService.open(this.dialogContent, options);
@@ -55,49 +71,62 @@ export class DialogComponent implements OnInit {
             setTimeout(() => this.onOpen$.emit(true));
         }
 
-        return new Promise( (resolve, reject) => {
+        return new Observable(observer => {
+            this.observer = observer;
 
             this.modalRef.result.then(
-                (result) => {
-                    resolve(result);
-                    this.modalRef = null;
-                },
-
-                (result) => {
-                    // NgbModal creates some result values for us, which
-                    // are outside of our control.  Other dismissal
-                    // reasons are agreed upon by implementing subclasses.
-                    console.debug('dialog closed with ' + result);
-
-                    const dismissed = (
-                           result === 0 // body click
-                        || result === 1 // Esc key
-                        || result === 'canceled' // Cancel button
-                        || result === 'cross_click' // modal top-right X
-                    );
-
-                    const rejection: DialogRejectionResponse = {
-                        dismissed: dismissed,
-                        message: result
-                    };
-
-                    reject(rejection);
-                    this.modalRef = null;
-                }
+                // Results are relayed to the caller via our observer.
+                // Our Observer is marked complete via this.close().
+                // Nothing to do here.
+                result => {},
+
+                // Modal was dismissed via UI control which
+                // bypasses call to this.close()
+                dismissed => this.finalize()
             );
         });
     }
 
-    close(reason?: any): void {
-        if (this.modalRef) {
-            this.modalRef.close(reason);
+    // Send a response to the caller without closing the dialog.
+    respond(value: any) {
+        if (this.observer && value !== undefined) {
+            this.observer.next(value);
+        }
+    }
+
+    // Sends error event to the caller and closes the dialog.
+    // Once an error is sent, our observable is complete and
+    // cannot be used again to send any messages.
+    error(value: any, close?: boolean) {
+        if (this.observer) {
+            console.error('Dialog produced error', value);
+            this.observer.error(value);
+            this.observer = null;
         }
+        if (this.modalRef) { this.modalRef.close(); }
+        this.finalize();
+    }
+
+    // Close the dialog, optionally with a value to relay to the caller.
+    // Calling close() with no value simply dismisses the dialog.
+    close(value?: any) {
+        this.respond(value);
+        if (this.modalRef) { this.modalRef.close(); }
+        this.finalize();
+    }
+
+    dismiss() {
+        console.warn('Dialog.dismiss() is deprecated.  Use close() instead');
+        this.close();
     }
 
-    dismiss(reason?: any): void {
-        if (this.modalRef) {
-            this.modalRef.dismiss(reason);
+    // Clean up after closing the dialog.
+    finalize() {
+        if (this.observer) { // null if this.error() called
+            this.observer.complete();
+            this.observer = null;
         }
+        this.modalRef = null;
     }
 }
 
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/progress.component.html b/Open-ILS/src/eg2/src/app/share/dialog/progress.component.html
index 78ca3d0c95..c1fdf20c0f 100644
--- a/Open-ILS/src/eg2/src/app/share/dialog/progress.component.html
+++ b/Open-ILS/src/eg2/src/app/share/dialog/progress.component.html
@@ -3,7 +3,7 @@
     <h4 *ngIf="dialogTitle" class="modal-title">{{dialogTitle}}</h4>
     <button type="button" class="close" 
       i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
diff --git a/Open-ILS/src/eg2/src/app/share/dialog/prompt.component.html b/Open-ILS/src/eg2/src/app/share/dialog/prompt.component.html
index 1d7936b176..17a6b50726 100644
--- a/Open-ILS/src/eg2/src/app/share/dialog/prompt.component.html
+++ b/Open-ILS/src/eg2/src/app/share/dialog/prompt.component.html
@@ -2,8 +2,7 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title">{{dialogTitle}}</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -17,6 +16,6 @@
     <button type="button" class="btn btn-success" 
       (click)="close(promptValue)" i18n>Confirm</button>
     <button type="button" class="btn btn-warning" 
-      (click)="dismiss('canceled')" i18n>Cancel</button>
+      (click)="close()" i18n>Cancel</button>
   </div>
 </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html
index 1b0935fb0a..5db749af35 100644
--- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html
+++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.html
@@ -5,13 +5,18 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title" i18n>Record Editor: {{recordLabel}}</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
   <div class="modal-body">
     <form #fmEditForm="ngForm" role="form" class="form-validated common-form striped-odd">
+      <ng-container *ngIf="!record">
+        <!-- display a progress dialog while the editor 
+            fetches the needed data -->
+        <eg-progress-inline></eg-progress-inline> 
+      </ng-container>
+      <ng-container *ngIf="record">
       <div class="form-group row" *ngFor="let field of fields">
         <div class="col-lg-3">
           <label for="{{idPrefix}}-{{field.name}}">{{field.label}}</label>
@@ -145,6 +150,7 @@
           </a>
         </div>
       </div>
+      </ng-container>
     </form>
   </div>
   <div class="modal-footer">
diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
index e9a4531113..e283cc2106 100644
--- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
+++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts
@@ -6,7 +6,7 @@ import {map} from 'rxjs/operators';
 import {AuthService} from '@eg/core/auth.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {DialogComponent} from '@eg/share/dialog/dialog.component';
-import {NgbModal, NgbModalOptions} from '@ng-bootstrap/ng-bootstrap';
+import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
 
@@ -173,14 +173,8 @@ export class FmRecordEditorComponent
 
         // Add some randomness to the generated DOM IDs to ensure against clobbering
         this.idPrefix = 'fm-editor-' + Math.floor(Math.random() * 100000);
-    }
 
-    // Opening dialog, fetch data.
-    open(options?: NgbModalOptions): Promise<any> {
-        return this.initRecord().then(
-            ok => super.open(options),
-            err => console.warn(`Error fetching FM data: ${err}`)
-        );
+        this.onOpen$.subscribe(() => this.initRecord());
     }
 
     // Set the record value and clear the recId value to
@@ -467,12 +461,12 @@ export class FmRecordEditorComponent
         this.convertDatatypesToIdl(recToSave);
         this.pcrud[this.mode]([recToSave]).toPromise().then(
             result => this.close(result),
-            error  => this.dismiss(error)
+            error  => this.error(error)
         );
     }
 
     cancel() {
-        this.dismiss('canceled');
+        this.close();
     }
 
     // Returns a string describing the type of input to display
diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html b/Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
index 3af756c9b9..1bb80fa6cf 100644
--- a/Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
+++ b/Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
@@ -2,8 +2,7 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title" i18n>Grid Columns Configuration</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
diff --git a/Open-ILS/src/eg2/src/app/staff/admin/workstation/workstations/workstations.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/workstation/workstations/workstations.component.ts
index a5c72e2dff..5ce77d42c1 100644
--- a/Open-ILS/src/eg2/src/app/staff/admin/workstation/workstations/workstations.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/admin/workstation/workstations/workstations.component.ts
@@ -121,16 +121,14 @@ export class WorkstationsComponent implements OnInit {
 
     private handleCollision(): Promise<number> {
         return new Promise((resolve, reject) => {
-            this.wsExistsDialog.open()
-            .then(
-                confirmed => {
+            this.wsExistsDialog.open().subscribe(override => {
+                if (override) {
                     this.registerWorkstationApi(true).then(
                         wsId => resolve(wsId),
                         notOk => reject(notOk)
                     );
-                },
-                dismissed => reject(dismissed)
-            );
+                }
+            });
         });
     }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts
index 0afc01d6fb..c33999a282 100644
--- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/match-set-list.component.ts
@@ -41,10 +41,8 @@ export class MatchSetListComponent implements AfterViewInit {
 
         this.createNew = () => {
             this.editDialog.mode = 'create';
-            this.editDialog.open({size: 'lg'}).then(
-                ok => this.grid.reload(),
-                err => {}
-            );
+            this.editDialog.open({size: 'lg'})
+                .subscribe(() => this.grid.reload());
         };
 
         this.deleteSelected = (matchSets: IdlObject[]) => {
@@ -62,10 +60,8 @@ export class MatchSetListComponent implements AfterViewInit {
             (matchSet: IdlObject) => {
                 this.editDialog.mode = 'update';
                 this.editDialog.recId = matchSet.id();
-                this.editDialog.open({size: 'lg'}).then(
-                    ok => this.grid.reload(),
-                    err => {}
-                );
+                this.editDialog.open({size: 'lg'})
+                    .subscribe(() => this.grid.reload());
             }
         );
     }
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.ts
index 9055f21cd4..19f08ad6ad 100644
--- a/Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/cat/vandelay/queue.component.ts
@@ -215,35 +215,26 @@ export class QueueComponent implements OnInit, AfterViewInit {
     }
 
     deleteQueue() {
-        this.confirmDelDlg.open().then(
-            yes => {
-                this.progressDlg.open();
-                return this.net.request(
-                    'open-ils.vandelay',
-                    `open-ils.vandelay.${this.qtypeShort()}_queue.delete`,
-                    this.auth.token(), this.queueId
-                ).toPromise();
-            },
-            no => {
-                this.progressDlg.close();
-                return Promise.reject('delete failed');
-            }
-        ).then(
-            resp => {
-                this.progressDlg.close();
-                const e = this.evt.parse(resp);
-                if (e) {
-                    console.error(e);
-                    alert(e);
-                } else {
+
+        this.confirmDelDlg.open().subscribe(confirmed => {
+            if (!confirmed) { return; }
+
+            this.progressDlg.open();
+            this.net.request(
+                'open-ils.vandelay',
+                `open-ils.vandelay.${this.qtypeShort()}_queue.delete`,
+                this.auth.token(), this.queueId
+            ).toPromise().then(
+                resp => {
+                    const e = this.evt.parse(resp);
+                    if (e) { return new Error(e.toString()); }
+
                     // Jump back to the main queue page.
                     this.router.navigate(['/staff/cat/vandelay/queue']);
-                }
-            },
-            err => {
-                this.progressDlg.close();
-            }
-        );
+                },
+                err => console.error('queue deletion failed!', err)
+            ).finally(() => this.progressDlg.close());
+        });
     }
 
     exportNonImported() {
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/part-merge-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/record/part-merge-dialog.component.html
index ef702ebfea..0beeefc7c5 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/record/part-merge-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/part-merge-dialog.component.html
@@ -2,8 +2,7 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title" i18n>Merge Monograph Parts</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -23,6 +22,6 @@
     <button type="button" class="btn btn-success" 
       (click)="mergeParts()" i18n>Merge</button>
     <button type="button" class="btn btn-warning" 
-      (click)="dismiss('canceled')" i18n>Cancel</button>
+      (click)="close()" i18n>Cancel</button>
   </div>
 </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/parts.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/parts.component.ts
index 3ab8e8f8e9..2f59374084 100644
--- a/Open-ILS/src/eg2/src/app/staff/catalog/record/parts.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/parts.component.ts
@@ -81,10 +81,8 @@ export class PartsComponent implements OnInit {
             (part: IdlObject) => {
                 this.editDialog.mode = 'update';
                 this.editDialog.recId = part.id();
-                this.editDialog.open().then(
-                    ok => this.partsGrid.reload(),
-                    err => {}
-                );
+                this.editDialog.open()
+                    .subscribe(ok => this.partsGrid.reload());
             }
         );
 
@@ -95,10 +93,7 @@ export class PartsComponent implements OnInit {
             this.editDialog.record = part;
 
             this.editDialog.mode = 'create';
-            this.editDialog.open().then(
-                ok => this.partsGrid.reload(),
-                err => {}
-            );
+            this.editDialog.open().subscribe(ok => this.partsGrid.reload());
         };
 
         this.deleteSelected = (parts: IdlObject[]) => {
@@ -113,10 +108,7 @@ export class PartsComponent implements OnInit {
         this.mergeSelected = (parts: IdlObject[]) => {
             if (parts.length < 2) { return; }
             this.mergeDialog.parts = parts;
-            this.mergeDialog.open().then(
-                ok => this.partsGrid.reload(),
-                err => console.debug('Dialog dismissed')
-            );
+            this.mergeDialog.open().subscribe(ok => this.partsGrid.reload());
         };
     }
 }
diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
index 6d4e2eaafc..de94b5ef74 100644
--- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts
@@ -158,15 +158,10 @@ export class SandboxComponent implements OnInit {
     }
 
     openEditor() {
-        this.fmRecordEditor.open({size: 'lg'}).then(
-            ok => { console.debug(ok); },
-            err => {
-                if (err && err.dismissed) {
-                    console.debug('dialog was dismissed');
-                } else {
-                    console.error(err);
-                }
-            }
+        this.fmRecordEditor.open({size: 'lg'}).subscribe(
+            pcrudResult => console.debug('Record editor performed action'),
+            err => console.error(err),
+            () => console.debug('Dialog closed')
         );
     }
 
diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
index 509f95cce6..2faf8f9d1d 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
+++ b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts
@@ -171,6 +171,91 @@ export class AdminPageComponent implements OnInit {
         this.grid.onRowActivate.subscribe(
             (idlThing: IdlObject) => this.showEditDialog(idlThing)
         );
+
+        this.editSelected = (idlThings: IdlObject[]) => {
+
+            // Edit each IDL thing one at a time
+            const editOneThing = (thing: IdlObject) => {
+                if (!thing) { return; }
+
+                this.showEditDialog(thing).then(
+                    () => editOneThing(idlThings.shift()));
+            };
+
+            editOneThing(idlThings.shift());
+        };
+
+        this.createNew = () => {
+            this.editDialog.mode = 'create';
+            // We reuse the same editor for all actions.  Be sure
+            // create action does not try to modify an existing record.
+            this.editDialog.recId = null;
+            this.editDialog.record = null;
+            this.editDialog.open({size: this.dialogSize}).subscribe(
+                result => {
+                    this.createString.current()
+                        .then(str => this.toast.success(str));
+                    this.grid.reload();
+                },
+                error => {
+                    this.createErrString.current()
+                        .then(str => this.toast.danger(str));
+                }
+            );
+        };
+
+        this.deleteSelected = (idlThings: IdlObject[]) => {
+            idlThings.forEach(idlThing => idlThing.isdeleted(true));
+            this.pcrud.autoApply(idlThings).subscribe(
+                val => console.debug('deleted: ' + val),
+                err => {},
+                ()  => this.grid.reload()
+            );
+        };
+
+        // Open the field translation dialog.
+        // Link the next/previous actions to cycle through each translatable
+        // field on each row.
+        this.translate = () => {
+            this.translateRowIdx = 0;
+            this.translateFieldIdx = 0;
+            this.translator.fieldName = this.translatableFields[this.translateFieldIdx];
+            this.translator.idlObject = this.dataSource.data[this.translateRowIdx];
+
+            this.translator.nextString = () => {
+
+                if (this.translateFieldIdx < this.translatableFields.length - 1) {
+                    this.translateFieldIdx++;
+
+                } else if (this.translateRowIdx < this.dataSource.data.length - 1) {
+                    this.translateRowIdx++;
+                    this.translateFieldIdx = 0;
+                }
+
+                this.translator.idlObject =
+                    this.dataSource.data[this.translateRowIdx];
+                this.translator.fieldName =
+                    this.translatableFields[this.translateFieldIdx];
+            };
+
+            this.translator.prevString = () => {
+
+                if (this.translateFieldIdx > 0) {
+                    this.translateFieldIdx--;
+
+                } else if (this.translateRowIdx > 0) {
+                    this.translateRowIdx--;
+                    this.translateFieldIdx = 0;
+                }
+
+                this.translator.idlObject =
+                    this.dataSource.data[this.translateRowIdx];
+                this.translator.fieldName =
+                    this.translatableFields[this.translateFieldIdx];
+            };
+
+            this.translator.open({size: 'lg'});
+        };
     }
 
     checkCreatePerms() {
@@ -262,22 +347,24 @@ export class AdminPageComponent implements OnInit {
         return this.contextOrg && this.contextOrg.children().length === 0;
     }
 
-    showEditDialog(idlThing: IdlObject) {
+    showEditDialog(idlThing: IdlObject): Promise<any> {
         this.editDialog.mode = 'update';
         this.editDialog.recId = idlThing[this.pkeyField]();
-        return this.editDialog.open({size: this.dialogSize}).then(
-            ok => {
-                this.successString.current()
-                    .then(str => this.toast.success(str));
-                this.grid.reload();
-            },
-            rejection => {
-                if (!rejection.dismissed) {
+        return new Promise((resolve, reject) => {
+            this.editDialog.open({size: this.dialogSize}).subscribe(
+                result => {
+                    this.successString.current()
+                        .then(str => this.toast.success(str));
+                    this.grid.reload();
+                    resolve(result);
+                },
+                error => {
                     this.updateFailedString.current()
                         .then(str => this.toast.danger(str));
+                    reject(error);
                 }
-            }
-        );
+            );
+        });
     }
 
     editSelected(idlThings: IdlObject[]) {
diff --git a/Open-ILS/src/eg2/src/app/staff/share/buckets/bucket-dialog.component.html b/Open-ILS/src/eg2/src/app/staff/share/buckets/bucket-dialog.component.html
index 32b6e2ec74..2c595487f6 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/buckets/bucket-dialog.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/buckets/bucket-dialog.component.html
@@ -10,8 +10,7 @@
       <span *ngIf="fromBibQueue" i18n>Add Records from queue #{{fromBibQueue}} to Bucket</span>
     </h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/op-change/op-change.component.html b/Open-ILS/src/eg2/src/app/staff/share/op-change/op-change.component.html
index e5a6f493b5..d472202999 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/op-change/op-change.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/op-change/op-change.component.html
@@ -2,8 +2,7 @@
   <div class="modal-header bg-info">
     <h4 class="modal-title" i18n>Change Operator</h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -60,6 +59,6 @@
   </div>
   <div class="modal-footer">
     <button (click)="login()" class="btn btn-info" i18n>OK/Continue</button>
-    <button (click)="dismiss('canceled')" class="btn btn-warning ml-2" i18n>Cancel</button>
+    <button (click)="close()" class="btn btn-warning ml-2" i18n>Cancel</button>
   </div>
 </ng-template>
diff --git a/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html b/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html
index 7aa59b46c3..61b9cb4f90 100644
--- a/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html
+++ b/Open-ILS/src/eg2/src/app/staff/share/translate/translate.component.html
@@ -4,8 +4,7 @@
       {{idlClassDef.label}}
     </h4>
     <button type="button" class="close" 
-      i18n-aria-label aria-label="Close" 
-      (click)="dismiss('cross_click')">
+      i18n-aria-label aria-label="Close" (click)="close()">
       <span aria-hidden="true">×</span>
     </button>
   </div>
@@ -58,6 +57,6 @@
     <button *ngIf="nextString" (click)="nextString()" 
       class="btn btn-info mr-3" i18n>Next String</button>
     <button (click)="translate()" class="btn btn-info" i18n>Apply</button>
-    <button (click)="dismiss('canceled')" class="btn btn-warning ml-2" i18n>Cancel</button>
+    <button (click)="close()" class="btn btn-warning ml-2" i18n>Cancel</button>
   </div>
 </ng-template>
diff --git a/Open-ILS/src/eg2/tsconfig.json b/Open-ILS/src/eg2/tsconfig.json
index 14a504dc91..157d6e6722 100644
--- a/Open-ILS/src/eg2/tsconfig.json
+++ b/Open-ILS/src/eg2/tsconfig.json
@@ -18,7 +18,8 @@
     ],
     "lib": [
       "es2017",
-      "dom"
+      "dom",
+      "es2018.promise"
     ]
   }
 }

-----------------------------------------------------------------------

Summary of changes:
 .../share/accesskey/accesskey-info.component.html  |   3 +-
 .../src/app/share/dialog/confirm.component.html    |   7 +-
 .../eg2/src/app/share/dialog/dialog.component.ts   | 115 +++++++++++++--------
 .../src/app/share/dialog/progress.component.html   |   2 +-
 .../eg2/src/app/share/dialog/prompt.component.html |   5 +-
 .../app/share/fm-editor/fm-editor.component.html   |  10 +-
 .../src/app/share/fm-editor/fm-editor.component.ts |  20 ++--
 .../share/grid/grid-column-config.component.html   |   3 +-
 .../staff/admin/server/org-unit-type.component.ts  |  47 +++++----
 .../workstations/workstations.component.ts         |  10 +-
 .../staff/cat/vandelay/match-set-list.component.ts |  12 +--
 .../src/app/staff/cat/vandelay/queue.component.ts  |  45 ++++----
 .../app/staff/catalog/basket-actions.component.ts  |   5 +-
 .../staff/catalog/record/conjoined.component.ts    |  49 +++++----
 .../app/staff/catalog/record/holdings.component.ts |  35 ++-----
 .../record/part-merge-dialog.component.html        |   5 +-
 .../app/staff/catalog/record/parts.component.ts    |  16 +--
 .../eg2/src/app/staff/sandbox/sandbox.component.ts |  13 +--
 .../staff/share/admin-page/admin-page.component.ts |  26 ++---
 .../booking/make-bookable-dialog.component.html    |   4 +-
 .../share/buckets/bucket-dialog.component.html     |   3 +-
 .../holdings/conjoined-items-dialog.component.html |   6 +-
 .../holdings/copy-alerts-dialog.component.html     |   4 +-
 .../share/holdings/copy-alerts-dialog.component.ts |  30 +++---
 .../holdings/delete-volcopy-dialog.component.html  |   6 +-
 .../holdings/delete-volcopy-dialog.component.ts    |   5 +-
 .../holdings/mark-damaged-dialog.component.html    |   6 +-
 .../holdings/mark-damaged-dialog.component.ts      |  20 ++--
 .../holdings/mark-missing-dialog.component.html    |   6 +-
 .../holdings/replace-barcode-dialog.component.html |   6 +-
 .../holdings/replace-barcode-dialog.component.ts   |  19 ++--
 .../staff/share/holds/cancel-dialog.component.html |   6 +-
 .../staff/share/holds/cancel-dialog.component.ts   |   3 +-
 .../src/app/staff/share/holds/grid.component.ts    |  27 ++---
 .../staff/share/holds/manage-dialog.component.html |   4 +-
 .../staff/share/holds/manage-dialog.component.ts   |   3 +-
 .../share/holds/retarget-dialog.component.html     |   6 +-
 .../staff/share/holds/retarget-dialog.component.ts |   3 +-
 .../share/holds/transfer-dialog.component.html     |   6 +-
 .../staff/share/holds/transfer-dialog.component.ts |   9 +-
 .../staff/share/op-change/op-change.component.html |   5 +-
 .../staff/share/translate/translate.component.html |   5 +-
 Open-ILS/src/eg2/tsconfig.json                     |   3 +-
 43 files changed, 305 insertions(+), 318 deletions(-)


hooks/post-receive
-- 
Evergreen ILS




More information about the open-ils-commits mailing list