working updates.

This commit is contained in:
Jason Kulatunga 2023-09-09 18:56:21 -07:00
parent 9e1c7455d1
commit 3c02bede7a
9 changed files with 106 additions and 8 deletions

View File

@ -5,7 +5,7 @@
<app-medical-sources-card class="col-sm-3 mg-b-20 px-3"
*ngFor="let sourceData of connectedSourceList"
[sourceInfo]="sourceData"
[status]="status[sourceData.metadata.source_type]"
[status]="status[sourceData.source.id] || status[sourceData.metadata.source_type]"
(onClick)="openModal(contentModalRef, $event)"
></app-medical-sources-card>
</div>

View File

@ -10,6 +10,7 @@ import {ToastNotification, ToastType} from '../../models/fasten/toast';
import {ToastService} from '../../services/toast.service';
import {ActivatedRoute, Router} from '@angular/router';
import {Location} from '@angular/common';
import {EventBusService} from '../../services/event-bus.service';
@Component({
selector: 'app-medical-sources-connected',
@ -33,6 +34,7 @@ export class MedicalSourcesConnectedComponent implements OnInit {
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
private eventBusService: EventBusService,
) { }
ngOnInit(): void {
@ -64,6 +66,9 @@ export class MedicalSourcesConnectedComponent implements OnInit {
.then(console.log)
}
this.eventBusService.eventBusSourceSyncMessages.subscribe((event) => {
this.status[event.source_id] = "token"
})
}
@ -171,6 +176,7 @@ export class MedicalSourcesConnectedComponent implements OnInit {
.subscribe((resp) => {
// const sourceSyncMessage = JSON.parse(msg) as SourceSyncMessage
delete this.status[sourceType]
delete this.status[resp.source.id]
// window.location.reload();
// this.connectedSourceList.
@ -269,7 +275,7 @@ export class MedicalSourcesConnectedComponent implements OnInit {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public openModal(contentModalRef, sourceListItem: SourceListItem) {
if(this.status[sourceListItem.metadata.source_type] || !sourceListItem.source){
if(this.status[sourceListItem.metadata.source_type] || !sourceListItem.source || this.status[sourceListItem.source.id]){
//if this source is currently "loading" dont open the modal window
return
}
@ -287,15 +293,17 @@ export class MedicalSourcesConnectedComponent implements OnInit {
public sourceSyncHandler(source: Source){
this.status[source.source_type] = "authorize"
this.status[source.id] = "authorize"
this.modalService.dismissAll()
this.fastenApi.syncSource(source.id).subscribe(
(respData) => {
delete this.status[source.id]
delete this.status[source.source_type]
console.log("source sync response:", respData)
},
(err) => {
delete this.status[source.id]
delete this.status[source.source_type]
console.log(err)
}

View File

@ -0,0 +1,3 @@
export interface Event {
event_type: string;
}

View File

@ -0,0 +1,4 @@
export interface EventSourceComplete extends Event {
event_type: string;
source_id: string;
}

View File

@ -0,0 +1,6 @@
export interface EventSourceSync extends Event {
event_type: string;
source_id: string;
resource_type: string;
resource_id: string;
}

View File

@ -10,6 +10,7 @@ import * as jose from 'jose';
import {UserRegisteredClaims} from '../models/fasten/user-registered-claims';
import {uuidV4} from '../../lib/utils/uuid';
import {HTTP_CLIENT_TOKEN} from "../dependency-injection";
import {BehaviorSubject, Observable, Subject} from 'rxjs';
@Injectable({
providedIn: 'root'
@ -17,7 +18,7 @@ import {HTTP_CLIENT_TOKEN} from "../dependency-injection";
export class AuthService {
FASTEN_JWT_LOCALSTORAGE_KEY = 'token';
public IsAuthenticatedSubject = new BehaviorSubject<boolean>(false)
constructor(@Inject(HTTP_CLIENT_TOKEN) private _httpClient: HttpClient) {
}
@ -129,17 +130,21 @@ export class AuthService {
this.setAuthToken(resp.data)
}
//TODO: now that we've moved to remote-first database, we can refactor and simplify this function significantly.
public async IsAuthenticated(): Promise<boolean> {
let authToken = this.GetAuthToken()
let hasAuthToken = !!authToken
if(!hasAuthToken){
this.publishAuthenticationState(false)
return false
}
//todo: check if the authToken has expired
return true
//check if the authToken has expired
let jwtClaims = jose.decodeJwt(authToken)
let valid = Date.now() < (jwtClaims.exp * 1000);
this.publishAuthenticationState(valid)
return valid
// //check if the authToken has expired.
// let databaseEndpointBase = GetEndpointAbsolutePath(globalThis.location, environment.couchdb_endpoint_base)
@ -180,6 +185,7 @@ export class AuthService {
}
public async Logout(): Promise<any> {
this.publishAuthenticationState(false)
return localStorage.removeItem(this.FASTEN_JWT_LOCALSTORAGE_KEY)
// // let remotePouchDb = new PouchDB(this.getRemoteUserDb(localStorage.getItem("current_user")), {skip_setup: true});
// if(this.pouchDb){
@ -192,6 +198,13 @@ export class AuthService {
/////////////////////////////////////////////////////////////////////////////////////////////////
private setAuthToken(token: string) {
this.publishAuthenticationState(true)
localStorage.setItem(this.FASTEN_JWT_LOCALSTORAGE_KEY, token)
}
private publishAuthenticationState(authenticated){
if(this.IsAuthenticatedSubject.value != authenticated){
this.IsAuthenticatedSubject.next(authenticated)
}
}
}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { EventBusService } from './event-bus.service';
describe('EventBusService', () => {
let service: EventBusService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(EventBusService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,48 @@
import {AfterViewInit, Injectable, OnInit} from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
import {BehaviorSubject, Observable, Subject, Subscription} from 'rxjs';
import {AuthService} from './auth.service';
import {FastenApiService} from './fasten-api.service';
import {ToastService} from './toast.service';
import {Event} from '../models/events/event';
import {EventSourceComplete} from '../models/events/event_source_complete';
import {EventSourceSync} from '../models/events/event_source_sync';
@Injectable({
providedIn: 'root'
})
export class EventBusService {
eventBusSubscription: Subscription | undefined;
eventBusSourceSyncMessages: Subject<EventSourceSync> = new Subject<EventSourceSync>();
eventBusSourceCompleteMessages: Subject<EventSourceComplete> = new Subject<EventSourceComplete>();
constructor(
public router: Router,
public authService: AuthService,
public fastenApiService: FastenApiService,
public toastService: ToastService
) {
// Ideally we want consistently listen to events, but only when the user is authenticated.
//TODO: find a way to abort the event bus connection.
this.authService.IsAuthenticatedSubject.subscribe((isAuthenticated) => {
console.log("isAuthenticated changed:", isAuthenticated)
if(isAuthenticated){
this.eventBusSubscription = this.fastenApiService.listenEventBus().subscribe((event: Event | EventSourceSync | EventSourceComplete)=>{
console.log("eventbus event:", event)
//TODO: start toasts.
if(event.event_type == "source_sync"){
this.eventBusSourceSyncMessages.next(event as EventSourceSync)
} else if(event.event_type == "source_complete"){
this.eventBusSourceCompleteMessages.next(event as EventSourceComplete)
}
})
} else {
//no longer authenticated, unsubscribe from eventbus
if(this.eventBusSubscription){
this.eventBusSubscription.unsubscribe()
}
}
});
}
}

View File

@ -65,7 +65,7 @@ export class FastenApiService {
'Authorization': `Bearer ${this.authService.GetAuthToken()}`
},
onmessage(ev) {
observer.next(ev.data);
observer.next(JSON.parse(ev.data));
},
onerror(event) {
observer.error(event)