LP1869898 Holdings responds to broadcasted changes
authorBill Erickson <berickxx@gmail.com>
Fri, 19 Jun 2020 20:50:18 +0000 (16:50 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Thu, 13 Aug 2020 15:16:31 +0000 (11:16 -0400)
Adds a new service for interracting with BroadcastChannel's.
Teaches the holdings grid to refresh data if a broadcast is received for
related holdings updates.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/eg2/src/app/share/util/broadcast.service.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/catalog/record/holdings.component.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts

diff --git a/Open-ILS/src/eg2/src/app/share/util/broadcast.service.ts b/Open-ILS/src/eg2/src/app/share/util/broadcast.service.ts
new file mode 100644 (file)
index 0000000..ccbb573
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * Create and consume BroadcastChannel broadcasts
+ */
+import {Injectable, EventEmitter} from '@angular/core';
+import {empty} from 'rxjs';
+
+interface BroadcastSub {
+    channel: any; // BroadcastChannel
+    emitter: EventEmitter<any>;
+}
+
+@Injectable()
+export class BroadcastService {
+
+    subscriptions: {[key: string]: BroadcastSub} = {};
+
+    noOpEmitter = new EventEmitter<any>();
+
+    listen(key: string): EventEmitter<any> {
+        if (typeof BroadcastChannel === 'undefined') {
+            return this.noOpEmitter;
+        }
+
+        if (this.subscriptions[key]) {
+            return this.subscriptions[key].emitter;
+        }
+
+        const emitter = new EventEmitter<any>();
+        const channel = new BroadcastChannel(key);
+
+        channel.onmessage = (e) => {
+            console.debug('Broadcast received', e.data);
+            emitter.emit(e.data);
+        };
+
+        this.subscriptions[key] = {
+            channel: channel,
+            emitter: emitter
+        };
+
+        return emitter;
+    }
+
+    broadcast(key: string, value: any) {
+        if (typeof BroadcastChannel === 'undefined') { return; }
+
+        if (this.subscriptions[key]) {
+            this.subscriptions[key].channel.postMessage(value);
+
+        } else {
+
+            // One time use channel
+            const channel = new BroadcastChannel(key);
+            channel.postMessage(value);
+            channel.close();
+        }
+    }
+
+    close(key: string) {
+        if (typeof BroadcastChannel === 'undefined') { return; }
+
+        if (this.subscriptions[key]) {
+            this.subscriptions[key].channel.close();
+            this.subscriptions[key].emitter.complete();
+            delete this.subscriptions[key];
+        }
+    }
+}
+
index 7a064a5..ed31980 100644 (file)
@@ -38,6 +38,7 @@ import {TransferItemsComponent
 import {TransferHoldingsComponent
     } from '@eg/staff/share/holdings/transfer-holdings.component';
 import {AlertDialogComponent} from '@eg/share/dialog/alert.component';
+import {BroadcastService} from '@eg/share/util/broadcast.service';
 
 
 // The holdings grid models a single HoldingsTree, composed of HoldingsTreeNodes
@@ -170,6 +171,7 @@ export class HoldingsMaintenanceComponent implements OnInit {
         private store: ServerStoreService,
         private localStore: StoreService,
         private holdings: HoldingsService,
+        private broadcaster: BroadcastService,
         private anonCache: AnonCacheService
     ) {
         // Set some sane defaults before settings are loaded.
@@ -230,6 +232,13 @@ export class HoldingsMaintenanceComponent implements OnInit {
     ngOnInit() {
         this.initDone = true;
 
+        this.broadcaster.listen('eg.holdings.update').subscribe(data => {
+            if (data && data.records && data.records.includes(this.recordId)) {
+                this.refreshHoldings = true;
+                this.holdingsGrid.reload();
+            }
+        });
+
         // These are pre-cached via the catalog resolver.
         const settings = this.store.getItemBatchCached([
             'cat.holdings_show_empty_org',
index 5b9645e..a2f54cf 100644 (file)
@@ -17,6 +17,7 @@ import {DatetimeValidatorDirective} from '@eg/share/validators/datetime_validato
 import {MultiSelectComponent} from '@eg/share/multi-select/multi-select.component';
 import {NotBeforeMomentValidatorDirective} from '@eg/share/validators/not_before_moment_validator.directive';
 import {PatronBarcodeValidatorDirective} from '@eg/share/validators/patron_barcode_validator.directive';
+import {BroadcastService} from '@eg/share/util/broadcast.service';
 
 /**
  * Imports the EG common modules and adds modules common to all staff UI's.
@@ -69,7 +70,8 @@ export class StaffCommonModule {
             ngModule: StaffCommonModule,
             providers: [ // Export staff-wide services
                 AccessKeyService,
-                AudioService
+                AudioService,
+                BroadcastService
             ]
         };
     }