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:
parent
61ed115dae
commit
9e7f6b5819
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
<div>
|
||||
<h3>INSIDE THE GERNERIC COMPONENT</h3>
|
||||
|
||||
<ngx-datatable
|
||||
#table
|
||||
class="bootstrap"
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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}`
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue