From 8509f6a858b634a278ab594448ab4c194300ba31 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 19 Jun 2020 16:50:18 -0400 Subject: [PATCH] LP1869898 Holdings responds to broadcasted changes 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 Signed-off-by: Jane Sandberg Signed-off-by: Galen Charlton --- .../src/app/share/util/broadcast.service.ts | 69 +++++++++++++++++++ .../catalog/record/holdings.component.ts | 9 +++ .../src/eg2/src/app/staff/common.module.ts | 4 +- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 Open-ILS/src/eg2/src/app/share/util/broadcast.service.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 index 0000000000..ccbb573a66 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/util/broadcast.service.ts @@ -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; +} + +@Injectable() +export class BroadcastService { + + subscriptions: {[key: string]: BroadcastSub} = {}; + + noOpEmitter = new EventEmitter(); + + listen(key: string): EventEmitter { + if (typeof BroadcastChannel === 'undefined') { + return this.noOpEmitter; + } + + if (this.subscriptions[key]) { + return this.subscriptions[key].emitter; + } + + const emitter = new EventEmitter(); + 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]; + } + } +} + 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 7a064a5468..ed31980213 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 @@ -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', diff --git a/Open-ILS/src/eg2/src/app/staff/common.module.ts b/Open-ILS/src/eg2/src/app/staff/common.module.ts index 5b9645e2ed..a2f54cf7ba 100644 --- a/Open-ILS/src/eg2/src/app/staff/common.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/common.module.ts @@ -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 ] }; } -- 2.43.2