UNPKG

ngx-gem-spaas

Version:

This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.

256 lines (248 loc) 11.8 kB
import * as i0 from '@angular/core'; import { Injectable, Optional, Inject, Component, Input, HostListener, NgModule } from '@angular/core'; import { BaseComponent } from 'ngx-gem-spaas'; import * as autobahn from 'autobahn-browser'; import { DateTime } from 'luxon'; import { Subject } from 'rxjs'; import * as i2 from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip'; import { CommonModule } from '@angular/common'; class CrossbarResponseModel { constructor(ts = '', topic = '') { this.topic = ''; this.type = ''; this.received = ts || DateTime.now().toISO(); this.topic = topic; } } class CrossbarSendModel { constructor() { this.type = ''; } } /** * Crossbar configuration object to be provided via "forRoot" method. * * @property {string} xbarUrl the URL of your crossbar websocket server * @property {string[]} xbarTopics the list of topics to listen to on the crossbar websocket server * @property {string} xbarTopicsPrefix prefix to be added to all topics, usually indicating the environment. * For example, on the Cylon xbar server, prefixes 'cb.preprod' and 'cb.prod' are used. Leave empty if none. */ class CrossbarConfigModel { constructor(props) { this.xbarUrl = ''; this.xbarTopics = []; this.xbarTopicsPrefix = ''; this.xbarTopics = props.xbarTopics || ['']; this.xbarTopicsPrefix = props.xbarTopicsPrefix || ''; this.xbarUrl = props.xbarUrl || ''; } } // @ts-ignore class CrossbarService { constructor(crossbarConfig) { this.crossbarConfig = crossbarConfig; this.crossbarMsg$ = new Subject(); } // ******************************************************************************************************** // AUTOBAHN // ******************************************************************************************************** startConnection() { if (!this.crossbarConfig?.xbarUrl || !this.crossbarConfig?.xbarTopics?.length) { throw new Error('please provide a valid SpaasCrossbarConfigModel using the forRoot method of the SpaasCrossbarModule'); } // CONNECT this.crossbar = new autobahn.Connection({ url: this.crossbarConfig.xbarUrl, realm: 'realm1', headers: { 'Authorization': btoa('none:none') } }); this.crossbar.open(); // CONNECT EVENTS this.crossbar.onopen = (session) => { // console.log('wsAutobahn opened'); this.crossbarSession = session; const resp = new CrossbarResponseModel(); resp.data = 'websocket connected successfully'; resp.type = 'connected'; let topics = this.crossbarConfig.xbarTopics || []; if (this.crossbarConfig.xbarTopicsPrefix) { topics = topics.map((t) => this.crossbarConfig.xbarTopicsPrefix + '.' + t); } topics.forEach((topic) => session.subscribe(topic, (args, kwargs, details) => this.onChannelUpdate(args, kwargs, details))); this.newWsMessage(resp); }; // CLOSE EVENT this.crossbar.onclose = (e) => { const resp = new CrossbarResponseModel(); if (e.wasClean) { console.log('wsAutobahn closed'); resp.data = 'disconnected'; resp.type = 'disconnected'; } else { console.log('wsAutobahn closed due to error'); // CLOSE WAS TRIGGERED BY AN ERROR (WS ERROR ALWAYS CALLS WS CLOSE) if (this.crossbar.readyState !== 1) { // FAILED CONNECTION resp.data = 'Failed to connect. Is the server running and are you connected to the internet?'; resp.type = 'error'; } else { // OTHER ERROR resp.data = JSON.stringify(e); resp.type = 'error'; } } this.newWsMessage(resp); }; // ERROR EVENT this.crossbar.onerror = (e) => { // TESTING ONLY console.log(e); }; // HARD DISCONNECT FROM BROWSER return () => { if (this.crossbar) { this.crossbar.close(); } }; } onChannelUpdate(args, kwargs, details) { const data = args[0]; const resp = new CrossbarResponseModel(); resp.data = data?.data || data; resp.topic = details.topic ? details.topic.replace(this.crossbarConfig.xbarTopicsPrefix + '.', '') : ''; resp.type = data?.type || ''; this.newWsMessage(resp); } stopConnection() { if (this.crossbar) { this.crossbar.close(); } } sendMessage(topic, e, excludeMe = false) { if (this.crossbar) { this.crossbarSession.publish(this.crossbarConfig.xbarTopicsPrefix ? this.crossbarConfig.xbarTopicsPrefix + '.' + topic : topic, [e], null, { exclude_me: excludeMe }); } } // ******************************************************************************************************** // BROADCAST DATA // ******************************************************************************************************** newWsMessage(msg) { // console.log(msg); this.crossbarMsg$.next(msg); } onNewWsMessage() { return this.crossbarMsg$.asObservable(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CrossbarService, deps: [{ token: CrossbarConfigModel, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CrossbarService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CrossbarService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: CrossbarConfigModel, decorators: [{ type: Optional }, { type: Inject, args: [CrossbarConfigModel] }] }] }); /** * This component creates the connection to the crossbar websocket server and * shows a state indicator in the bottom left corner of your app. * */ class CrossbarStateComponent extends BaseComponent { constructor(crossbarService) { super(); this.crossbarService = crossbarService; this.fromBottomPx = 14; this.crossbarActive = false; } onFocus() { // ALSO CHECK IF TAB IS VISIBLE if (document.visibilityState !== 'hidden') { this.crossbarConnect(); } } ngOnInit() { this.crossbarConnect(); } ngOnDestroy() { this.crossbarService.stopConnection(); super.ngOnDestroy(); } // ******************************************************************************************************** // LOADING DATA // ******************************************************************************************************** crossbarConnect() { if (!this.crossbarService.crossbar || !this.crossbarService.crossbar.isConnected || !this.crossbarService.crossbar.isOpen) { this.crossbarService.startConnection(); this.wsCrossbarSubscribe(); } else { this.crossbarActive = true; } } wsCrossbarSubscribe() { this.crossbarService.onNewWsMessage() .subscribe((responseData) => { if (responseData.type === 'connected') { // DO NOTHING, JUST WS CONNECTING this.crossbarActive = true; } else if (responseData.type === 'error' || responseData.type === 'disconnected') { // DO NOTHING, ERROR OR DISCONNECT => XBAR RECONNECTS AUTOMATICALLY this.crossbarActive = false; } }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CrossbarStateComponent, deps: [{ token: CrossbarService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CrossbarStateComponent, selector: "spaas-crossbar", inputs: { fromBottomPx: "fromBottomPx" }, host: { listeners: { "window:focus": "onFocus($event)" } }, usesInheritance: true, ngImport: i0, template: "<div [class.nok]=\"!crossbarActive\"\r\n [class.ok]=\"crossbarActive\"\r\n [style.bottom.px]=\"fromBottomPx\"\r\n class=\"ws-state\"\r\n matTooltip=\"{{crossbarActive ? 'live update OK' : 'live update NOK'}}\">\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CrossbarStateComponent, decorators: [{ type: Component, args: [{ selector: 'spaas-crossbar', template: "<div [class.nok]=\"!crossbarActive\"\r\n [class.ok]=\"crossbarActive\"\r\n [style.bottom.px]=\"fromBottomPx\"\r\n class=\"ws-state\"\r\n matTooltip=\"{{crossbarActive ? 'live update OK' : 'live update NOK'}}\">\r\n</div>\r\n" }] }], ctorParameters: () => [{ type: CrossbarService }], propDecorators: { fromBottomPx: [{ type: Input }], onFocus: [{ type: HostListener, args: ['window:focus', ['$event']] }] } }); class SpaasCrossbarModule { static forRoot(config) { return { ngModule: SpaasCrossbarModule, providers: [{ provide: CrossbarConfigModel, useValue: config }] }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasCrossbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: SpaasCrossbarModule, declarations: [CrossbarStateComponent], imports: [CommonModule, MatTooltipModule], exports: [CrossbarStateComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasCrossbarModule, imports: [CommonModule, MatTooltipModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasCrossbarModule, decorators: [{ type: NgModule, args: [{ declarations: [ CrossbarStateComponent, ], exports: [ CrossbarStateComponent, ], imports: [ CommonModule, MatTooltipModule, ], providers: [] }] }] }); // MODULE /** * Generated bundle index. Do not edit. */ export { CrossbarConfigModel, CrossbarResponseModel, CrossbarSendModel, CrossbarService, CrossbarStateComponent, SpaasCrossbarModule }; //# sourceMappingURL=ngx-gem-spaas-crossbar.mjs.map