adding list fallback for unknown components (so users can still see the raw data).

Make sure patient information is included in the header for the source detail page.
This commit is contained in:
Jason Kulatunga 2022-09-25 21:02:12 -07:00
parent 61ed115dae
commit 9e7f6b5819
12 changed files with 168 additions and 5 deletions

View File

@ -0,0 +1,14 @@
<div class="alert alert-warning" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>Warning!</strong> Fasten does not know how to display this resource type (yet). Click an item in the list below to see the raw data
</div>
<ul class="list-group">
<li class="list-group-item" *ngFor="let resource of resourceList">
<a routerLink="/source/{{resource.source_id}}/resource/{{resource.source_resource_id}}">{{resource.source_resource_id}}</a>
</li>
</ul>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ListFallbackResourceComponent } from './list-fallback-resource.component';
describe('ListFallbackResourceComponent', () => {
let component: ListFallbackResourceComponent;
let fixture: ComponentFixture<ListFallbackResourceComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ListFallbackResourceComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(ListFallbackResourceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,24 @@
import {ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';
import {ResourceFhir} from '../../models/fasten/resource_fhir';
import {ResourceListComponentInterface} from '../list-generic-resource/list-generic-resource.component';
import {Router} from '@angular/router';
@Component({
selector: 'app-list-fallback-resource',
templateUrl: './list-fallback-resource.component.html',
styleUrls: ['./list-fallback-resource.component.scss']
})
export class ListFallbackResourceComponent implements OnInit, ResourceListComponentInterface {
@Input() resourceList: ResourceFhir[] = []
constructor(public changeRef: ChangeDetectorRef, public router: Router) {}
ngOnInit(): void {
console.log("RESOURCE LIST INSIDE FALLBACK", this.resourceList)
}
markForCheck(){
this.changeRef.markForCheck()
}
}

View File

@ -1,6 +1,4 @@
<div>
<h3>INSIDE THE GERNERIC COMPONENT</h3>
<ngx-datatable
#table
class="bootstrap"

View File

@ -29,6 +29,7 @@ import {ListAppointmentComponent} from '../list-generic-resource/list-appointmen
import {ListDeviceComponent} from '../list-generic-resource/list-device.component';
import {ListDiagnosticReportComponent} from '../list-generic-resource/list-diagnostic-report.component';
import {ListGoalComponent} from '../list-generic-resource/list-goal.component';
import {ListFallbackResourceComponent} from '../list-fallback-resource/list-fallback-resource.component';
@Component({
selector: 'source-resource-list',
@ -90,6 +91,10 @@ export class ResourceListComponent implements OnInit, OnChanges {
}
typeLookup(resourceType: string): Type<any> {
if(!resourceType){
//dont try to render anything if the resourceType isnt set.
return null
}
switch(resourceType) {
case "Appointment": {
return ListAppointmentComponent;
@ -158,8 +163,8 @@ export class ResourceListComponent implements OnInit, OnChanges {
return ListServiceRequestComponent;
}
default: {
console.error("UNKNOWN COMPONENT TYPE", resourceType)
return null
console.warn("Unknown component type, using fallback", resourceType)
return ListFallbackResourceComponent;
}
}

View File

@ -30,6 +30,7 @@ import {ListAppointmentComponent} from './list-generic-resource/list-appointment
import {ListDeviceComponent} from './list-generic-resource/list-device.component';
import {ListDiagnosticReportComponent} from './list-generic-resource/list-diagnostic-report.component';
import {ListGoalComponent} from './list-generic-resource/list-goal.component';
import { ListFallbackResourceComponent } from './list-fallback-resource/list-fallback-resource.component';
@NgModule({
imports: [
@ -66,6 +67,7 @@ import {ListGoalComponent} from './list-generic-resource/list-goal.component';
ListGoalComponent,
ResourceListComponent,
ResourceListOutletDirective,
ListFallbackResourceComponent,
],
exports: [
ComponentsSidebarComponent,

View File

@ -1,4 +1,5 @@
import {Source} from './source';
import {ResourceFhir} from './resource_fhir';
export class ResourceTypeCounts {
count: number
@ -9,4 +10,5 @@ export class ResourceTypeCounts {
export class SourceSummary {
source: Source
resource_type_counts: ResourceTypeCounts[]
patient?: ResourceFhir
}

View File

@ -144,7 +144,7 @@
<td class="align-middle">
<div class="media">
<img [src]="'assets/sources/'+source.source_type+'.png'"
alt="Geeks"
alt="{{source.source_type}}"
class="mr-3"
style="width:100px;">
<div class="media-body">

View File

@ -1,5 +1,52 @@
<div class="az-content">
<div class="container bg-light mb-4 p-2">
<div class="az-content-body">
<div class="panel panel-default patient col-xs-12">
<div class="row">
<div class="col-xs-2 col-sm-2 col-md-1">
<div class="">
<div class="patient-image-wrap embed-responsive-item">
<img [src]="'assets/sources/'+selectedSource.source_type+'.png'"
alt="{{selectedSource.source_type}}"
class="img-fluid">
</div>
</div>
</div>
<div class="col-xs-10 col-md-11">
<div class="patient-row row">
<div class="col-7 patient-name"><h3 class="pull-left text-primary">{{getPatientName()}}</h3></div>
<div class="col-5">
<a routerLink="/source/{{selectedSource.id}}/resource/{{selectedPatient.source_resource_id}}" class="btn btn-indigo btn-icon float-right">
<i class="fas fa-info-circle"></i>
</a>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">Gender:</div>
<div class="col-xs-8 col-sm-3 col-lg-3 text-left p-0">{{getPatientGender()}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">DOB:</div>
<div class="col-xs-8 col-sm-5 col-lg-3 text-left p-0">{{getPatientDOB()}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">Age:</div>
<div class="col-xs-8 col-sm-3 col-lg-3 text-left p-0">58 year</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">Email</div>
<div class="col-xs-8 col-sm-5 col-lg-3 text-left p-0">{{getPatientEmail()}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">Phone:</div>
<div class="col-xs-8 col-sm-3 col-lg-3 text-left p-0">{{getPatientPhone()}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">Address:</div>
<div class="col-xs-8 col-sm-5 col-lg-3 text-left p-0">{{getPatientAddress()}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">ID:</div>
<div class="col-xs-8 col-sm-3 col-lg-3 text-left p-0">{{selectedPatient?.source_resource_id}}</div>
<div class="col-xs-4 col-sm-2 col-lg-1 text-right text-muted">MRN:</div>
<div class="col-xs-8 col-sm-5 col-lg-3 text-left p-0">{{getPatientMRN()}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="az-content-left">
<div class="az-content-breadcrumb">

View File

@ -2,6 +2,8 @@ import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Source} from '../../models/fasten/source';
import {FastenApiService} from '../../services/fasten-api.service';
import {ResourceFhir} from '../../models/fasten/resource_fhir';
import {getPath} from '../../components/list-generic-resource/utils';
@Component({
@ -12,6 +14,7 @@ import {FastenApiService} from '../../services/fasten-api.service';
export class SourceDetailComponent implements OnInit {
selectedSource: Source = null
selectedPatient: ResourceFhir = null
selectedResourceType: string = null
resourceTypeCounts: { [name: string]: number } = {}
@ -27,6 +30,7 @@ export class SourceDetailComponent implements OnInit {
//always request the source summary
this.fastenApi.getSourceSummary(this.route.snapshot.paramMap.get('source_id')).subscribe((sourceSummary) => {
this.selectedSource = sourceSummary.source;
this.selectedPatient = sourceSummary.patient;
for(let resourceTypeCount of sourceSummary.resource_type_counts){
this.resourceTypeCounts[resourceTypeCount.resource_type] = resourceTypeCount.count
}
@ -36,4 +40,42 @@ export class SourceDetailComponent implements OnInit {
selectResourceType(resourceType: string) {
this.selectedResourceType = resourceType
}
//functions to call on patient
getPatientName(){
// @ts-ignore
return `${getPath(this.selectedPatient?.payload, 'name.0.family')}, ${getPath(this.selectedPatient?.payload, 'name.0.given').join(' ')}`
}
getPatientGender(){
return getPath(this.selectedPatient?.payload, 'gender')
}
getPatientMRN(){
return getPath(this.selectedPatient?.payload, 'identifier.0.value')
}
getPatientEmail(){
// @ts-ignore
return (this.selectedPatient?.payload?.telecom || []).filter(
telecom => telecom.system === 'email',
)[0]?.value
}
getPatientDOB(){
return getPath(this.selectedPatient?.payload, 'birthDate')
}
getPatientPhone(){
// @ts-ignore
return (this.selectedPatient?.payload?.telecom || []).filter(
telecom => telecom.system === 'phone',
)[0]?.value
}
getPatientAge(){
return ''
}
getPatientAddress(){
const line = getPath(this.selectedPatient?.payload, 'address.0.line')
const city = getPath(this.selectedPatient?.payload, 'address.0.city')
const state = getPath(this.selectedPatient?.payload, 'address.0.state')
return `${line}, ${city}, ${state}`
}
}

View File

@ -15,6 +15,12 @@
cursor: auto !important;
}
// if text is too long, we can truncate
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* You can add global styles to this file, and also import other style files */
/*