From 74fc682dbf1f6ac67653dc61d0483d615352362e Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Fri, 8 Sep 2023 14:10:37 -0700 Subject: [PATCH] renamed sse endpoint to events. Using the technology name in the API isnt a good idea. --- backend/pkg/web/server.go | 2 +- .../app/components/toast/toast.component.ts | 30 ++++++++++++++++++- .../src/app/services/fasten-api.service.ts | 24 +++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/backend/pkg/web/server.go b/backend/pkg/web/server.go index c41523ab..a4d8b500 100644 --- a/backend/pkg/web/server.go +++ b/backend/pkg/web/server.go @@ -79,7 +79,7 @@ func (ae *AppEngine) Setup() (*gin.RouterGroup, *gin.Engine) { secure.POST("/query", handler.QueryResourceFhir) //server-side-events handler - secure.GET("/sse/stream", middleware.SSEHeaderMiddleware(), middleware.SSEEventBusServerMiddleware(), handler.SSEStream) + secure.GET("/events/stream", middleware.SSEHeaderMiddleware(), middleware.SSEEventBusServerMiddleware(), handler.SSEStream) } if ae.Config.GetBool("web.allow_unsafe_endpoints") { diff --git a/frontend/src/app/components/toast/toast.component.ts b/frontend/src/app/components/toast/toast.component.ts index a4d4301d..69885e13 100644 --- a/frontend/src/app/components/toast/toast.component.ts +++ b/frontend/src/app/components/toast/toast.component.ts @@ -1,5 +1,9 @@ import {Component, OnInit, TemplateRef} from '@angular/core'; import {ToastService} from '../../services/toast.service'; +import {AuthService} from '../../services/auth.service'; +import {FastenApiService} from '../../services/fasten-api.service'; +import {Subscription} from 'rxjs'; +import {NavigationEnd, Router} from '@angular/router'; @Component({ selector: 'app-toast', @@ -7,9 +11,33 @@ import {ToastService} from '../../services/toast.service'; styleUrls: ['./toast.component.scss'] }) export class ToastComponent implements OnInit { + routerSubscription: Subscription | undefined; - constructor(public toastService: ToastService) {} + constructor( + public router: Router, + public toastService: ToastService, + public authService: AuthService, + public fastenApiService: FastenApiService, + ) {} ngOnInit(): void { + + } + ngAfterViewInit() { + //TODO: this is a bit kludgey. + // Ideally we want consistently listen to events, but only when the user is authenticated. + this.routerSubscription = this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + if(!event.url.startsWith("/auth") && this.authService.IsAuthenticated()){ + console.log("user is authenticated, listening for notifications") + //user is authenticated, lets start listening for notifications + this.routerSubscription?.unsubscribe() + this.fastenApiService.listenEventBus().subscribe((event)=>{ + console.log("eventbus event:", event) + //TODO: start toasts. + }) + } + } + }); } } diff --git a/frontend/src/app/services/fasten-api.service.ts b/frontend/src/app/services/fasten-api.service.ts index d318ef5f..4aeec2f9 100644 --- a/frontend/src/app/services/fasten-api.service.ts +++ b/frontend/src/app/services/fasten-api.service.ts @@ -22,6 +22,7 @@ import * as fhirpath from 'fhirpath'; import _ from 'lodash'; import {DashboardConfig} from '../models/widget/dashboard-config'; import {DashboardWidgetQuery} from '../models/widget/dashboard-widget-query'; +import { fetchEventSource } from '@microsoft/fetch-event-source'; @Injectable({ providedIn: 'root' @@ -54,6 +55,29 @@ export class FastenApiService { SECURE ENDPOINTS */ + listenEventBus(): Observable { + let eventStreamUrl = `${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/events/stream` + + return new Observable(observer => { + fetchEventSource(eventStreamUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.authService.GetAuthToken()}` + }, + onmessage(ev) { + observer.next(ev.data); + }, + onerror(event) { + observer.error(event) + }, + }).then( + () => observer.complete(), + error => observer.error(error) + ) + }); + } + getDashboards(): Observable { return this._httpClient.get(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/dashboards`, ) .pipe(