adding source summary endpoint
added generic resource list component added resource-list outlet directive and component.
This commit is contained in:
parent
48c8873f18
commit
7bced71569
|
@ -22,5 +22,6 @@ type DatabaseRepository interface {
|
||||||
|
|
||||||
CreateSource(context.Context, *models.Source) error
|
CreateSource(context.Context, *models.Source) error
|
||||||
GetSource(context.Context, string) (*models.Source, error)
|
GetSource(context.Context, string) (*models.Source, error)
|
||||||
|
GetSourceSummary(context.Context, string) (*models.SourceSummary, error)
|
||||||
GetSources(context.Context) ([]models.Source, error)
|
GetSources(context.Context) ([]models.Source, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,40 @@ func (sr *sqliteRepository) GetSource(ctx context.Context, sourceId string) (*mo
|
||||||
return &sourceCred, results.Error
|
return &sourceCred, results.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sr *sqliteRepository) GetSourceSummary(ctx context.Context, sourceId string) (*models.SourceSummary, error) {
|
||||||
|
sourceUUID, err := uuid.Parse(sourceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSummary := &models.SourceSummary{}
|
||||||
|
|
||||||
|
source, err := sr.GetSource(ctx, sourceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sourceSummary.Source = source
|
||||||
|
|
||||||
|
//group by resource type and return counts
|
||||||
|
// SELECT source_resource_type as resource_type, COUNT(*) as count FROM resource_fhirs WHERE source_id = "53c1e930-63af-46c9-b760-8e83cbc1abd9" GROUP BY source_resource_type;
|
||||||
|
|
||||||
|
var results []map[string]interface{}
|
||||||
|
|
||||||
|
sr.gormClient.WithContext(ctx).
|
||||||
|
Model(models.ResourceFhir{}).
|
||||||
|
Select("source_id, source_resource_type as resource_type, count(*) as count").
|
||||||
|
Group("source_resource_type").
|
||||||
|
Where(models.OriginBase{
|
||||||
|
UserID: sr.GetCurrentUser(ctx).ID,
|
||||||
|
SourceID: sourceUUID,
|
||||||
|
}).
|
||||||
|
Scan(&results)
|
||||||
|
|
||||||
|
sourceSummary.ResourceTypeCounts = results
|
||||||
|
|
||||||
|
return sourceSummary, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sr *sqliteRepository) GetSources(ctx context.Context) ([]models.Source, error) {
|
func (sr *sqliteRepository) GetSources(ctx context.Context) ([]models.Source, error) {
|
||||||
|
|
||||||
var sourceCreds []models.Source
|
var sourceCreds []models.Source
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type SourceSummary struct {
|
||||||
|
Source *Source `json:"source,omitempty"`
|
||||||
|
ResourceTypeCounts []map[string]interface{} `json:"resource_type_counts,omitempty"`
|
||||||
|
}
|
|
@ -118,6 +118,19 @@ func GetSource(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCred})
|
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCred})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSourceSummary(c *gin.Context) {
|
||||||
|
logger := c.MustGet("LOGGER").(*logrus.Entry)
|
||||||
|
databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository)
|
||||||
|
|
||||||
|
sourceSummary, err := databaseRepo.GetSourceSummary(c, c.Param("sourceId"))
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorln("An error occurred while retrieving source summary", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceSummary})
|
||||||
|
}
|
||||||
|
|
||||||
func ListSource(c *gin.Context) {
|
func ListSource(c *gin.Context) {
|
||||||
logger := c.MustGet("LOGGER").(*logrus.Entry)
|
logger := c.MustGet("LOGGER").(*logrus.Entry)
|
||||||
databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository)
|
databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository)
|
||||||
|
|
|
@ -49,6 +49,7 @@ func (ae *AppEngine) Setup(logger *logrus.Entry) *gin.Engine {
|
||||||
secure.POST("/source/manual", handler.CreateManualSource)
|
secure.POST("/source/manual", handler.CreateManualSource)
|
||||||
secure.GET("/source", handler.ListSource)
|
secure.GET("/source", handler.ListSource)
|
||||||
secure.GET("/source/:sourceId", handler.GetSource)
|
secure.GET("/source/:sourceId", handler.GetSource)
|
||||||
|
secure.GET("/source/:sourceId/summary", handler.GetSourceSummary)
|
||||||
//in debug mode, this endpoint lets us request data directly from the source api
|
//in debug mode, this endpoint lets us request data directly from the source api
|
||||||
secure.GET("/source/raw/:sourceType/*path", handler.RawRequestSource)
|
secure.GET("/source/raw/:sourceType/*path", handler.RawRequestSource)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ import { CanActivateAuthGuard } from './services/can-activate.auth-guard';
|
||||||
import {FastenApiService} from './services/fasten-api.service';
|
import {FastenApiService} from './services/fasten-api.service';
|
||||||
import {Router} from '@angular/router';
|
import {Router} from '@angular/router';
|
||||||
import { SourceDetailComponent } from './pages/source-detail/source-detail.component';
|
import { SourceDetailComponent } from './pages/source-detail/source-detail.component';
|
||||||
|
import { ResourceListOutletDirective } from './directive/resource-list-outlet.directive';
|
||||||
|
import {ResourceListComponent} from './components/resource-list/resource-list.component';
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<p class="mg-b-20">A clinical condition, problem, diagnosis, or other event, situation, issue, or clinical concept that has risen to a level of concern.</p>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered mg-b-0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Category</th>
|
|
||||||
<th>Reason</th>
|
|
||||||
<th>Period</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr *ngFor="let careplan of careplanList">
|
|
||||||
<td>
|
|
||||||
<b>{{careplan.category}}</b>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">
|
|
||||||
<div *ngFor="let reason of careplan.reason">
|
|
||||||
{{reason[0]}}
|
|
||||||
<span> - </span>
|
|
||||||
<span className="text-muted">
|
|
||||||
{{reason[1] || "no data"}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="align-middle">{{careplan.period?.start}} - {{careplan.period?.end}}</td>
|
|
||||||
<td class="align-middle">{{careplan.status}}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
|
@ -1,25 +0,0 @@
|
||||||
import {Component, Input, OnInit} from '@angular/core';
|
|
||||||
import {ResourceFhir} from '../../models/fasten/resource_fhir';
|
|
||||||
import {CarePlan} from '../../models/display/care-plan';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-list-care-plan',
|
|
||||||
templateUrl: './list-care-plan.component.html',
|
|
||||||
styleUrls: ['./list-care-plan.component.scss']
|
|
||||||
})
|
|
||||||
export class ListCarePlanComponent implements OnInit {
|
|
||||||
|
|
||||||
@Input() resourceList: ResourceFhir[] = []
|
|
||||||
careplanList: CarePlan[] = []
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
let _careplanList = this.careplanList
|
|
||||||
this.resourceList.forEach((resource) => {
|
|
||||||
let careplan = new CarePlan(resource.payload)
|
|
||||||
_careplanList.push(careplan)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
<p>list-explanation-of-benefit works!</p>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { ListExplanationOfBenefitComponent } from './list-explanation-of-benefit.component';
|
|
||||||
|
|
||||||
describe('ListExplanationOfBenefitComponent', () => {
|
|
||||||
let component: ListExplanationOfBenefitComponent;
|
|
||||||
let fixture: ComponentFixture<ListExplanationOfBenefitComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [ ListExplanationOfBenefitComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(ListExplanationOfBenefitComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-list-explanation-of-benefit',
|
|
||||||
templateUrl: './list-explanation-of-benefit.component.html',
|
|
||||||
styleUrls: ['./list-explanation-of-benefit.component.scss']
|
|
||||||
})
|
|
||||||
export class ListExplanationOfBenefitComponent implements OnInit {
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-adverse-event',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListAdverseEventComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Event', versions: '*', format: 'code', getter: a => a.event.coding[0] },
|
||||||
|
{ title: 'Date', versions: '*', format: 'date', getter: a => a.date }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-allergy-intolerance',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListAllergyIntoleranceComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Allergy', versions: '*', format: 'code', getter: a => a.code.coding[0] },
|
||||||
|
{ title: 'Date Recorded', versions: '*', format: 'date', getter: a => a.assertedDate || a.recordedDate },
|
||||||
|
{ title: 'Onset', versions: '*', format: 'date', getter: a => a.onsetDateTime },
|
||||||
|
{ title: 'Resolution Age', versions: '*', format: 'date', getter: a => a.extension.resolutionAge }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
import {getPath} from '../../fhir/utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-care-plan',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListCarePlanComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Category', versions: '*', format: 'code', getter: c => c.category[0].coding[0] },
|
||||||
|
{ title: 'Reason', versions: '*', getter: c => {
|
||||||
|
return (c.activity || []).map((a, i) => {
|
||||||
|
let reason = getPath(a, "detail.code.coding.0.display") || ""
|
||||||
|
return reason ? [reason, getPath(a, "detail.status") || "no data"] : []
|
||||||
|
})
|
||||||
|
} },
|
||||||
|
{ title: 'Period', versions: '*', format: 'period', getter: c => c.period },
|
||||||
|
{ title: 'Status', versions: '*', getter: a => a.status },
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-communication',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListCommunicationComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Reason', versions: '*', format: 'code', getter: c => c.reasonCode[0].coding[0] },
|
||||||
|
{ title: 'Sent', versions: '*', format: 'date', getter: c => c.sent },
|
||||||
|
{ title: 'Received', versions: '*', format: 'date', getter: c => c.received },
|
||||||
|
{ title: 'Status', versions: '*', getter: c => c.status }
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import {Component} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
import {GenericColumnDefn, ListGenericResourceComponent, ResourceListComponentInterface} from './list-generic-resource.component';
|
||||||
|
import {FORMATTERS} from './utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-condition',
|
selector: 'app-list-condition',
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-coverage',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListCoverageComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Type', versions: '*', format: 'code', getter: c => c.type.coding[0] },
|
||||||
|
{ title: 'Period', versions: '*', format: 'period', getter: c => c.period }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-device-request',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListDeviceRequestComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Device', versions: '*', format: 'code', getter: d => d.codeCodeableConcept.coding[0] },
|
||||||
|
{ title: 'Author Date', versions: '*', format: 'date', getter: d => d.authoredOn },
|
||||||
|
{ title: 'Do Not Perform', versions: '*', getter: d => d.modifierExtension.doNotPerform },
|
||||||
|
{ title: 'Do Not Perform Reason', versions: '*', format: 'code', getter: s => s.extension.doNotPerformReason.coding[0] }
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-document-reference',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListDocumentReferenceComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Date', versions: '*', format: 'date', getter: d => d.date },
|
||||||
|
{ title: 'Content', versions: '*', getter: d => atob(d.content[0].attachment.data) }
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
import {Component} from '@angular/core';
|
import {Component, OnChanges, OnInit} from '@angular/core';
|
||||||
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
import {GenericColumnDefn, ListGenericResourceComponent, ResourceListComponentInterface} from './list-generic-resource.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-encounter',
|
selector: 'app-list-encounter',
|
||||||
templateUrl: './list-generic-resource.component.html',
|
templateUrl: './list-generic-resource.component.html',
|
||||||
styleUrls: ['./list-generic-resource.component.scss']
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
})
|
})
|
||||||
export class ListEncounterComponent extends ListGenericResourceComponent {
|
export class ListEncounterComponent extends ListGenericResourceComponent {
|
||||||
columnDefinitions: GenericColumnDefn[] = [
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
{ title: 'Encounter', versions: '*', format: 'code', getter: e => e.type[0].coding[0] },
|
{ title: 'Encounter', versions: '*', format: 'code', getter: e => e.type[0].coding[0] },
|
||||||
{ title: 'Period', versions: '*', format: 'period', getter: e => e.period },
|
{ title: 'Period', versions: '*', format: 'period', getter: e => e.period },
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import {Component, OnChanges, OnInit} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent, ResourceListComponentInterface} from './list-generic-resource.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-explanation-of-benefit',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListExplanationOfBenefitComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = []
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
<div>
|
<div>
|
||||||
|
<h3>INSIDE THE GERNERIC COMPONENT</h3>
|
||||||
|
|
||||||
<ngx-datatable
|
<ngx-datatable
|
||||||
#table
|
#table
|
||||||
class="bootstrap"
|
class="bootstrap"
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
import {ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core';
|
||||||
import {DatatableComponent, ColumnMode} from '@swimlane/ngx-datatable';
|
import {DatatableComponent, ColumnMode} from '@swimlane/ngx-datatable';
|
||||||
import {ResourceFhir} from '../../models/fasten/resource_fhir';
|
import {ResourceFhir} from '../../models/fasten/resource_fhir';
|
||||||
import {FORMATTERS, getPath, obsValue, attributeXTime} from './utils';
|
import {FORMATTERS, getPath, obsValue, attributeXTime} from './utils';
|
||||||
import {observableToBeFn} from 'rxjs/internal/testing/TestScheduler';
|
import {observableToBeFn} from 'rxjs/internal/testing/TestScheduler';
|
||||||
|
|
||||||
|
|
||||||
|
//all Resource list components must implement this Interface
|
||||||
|
export interface ResourceListComponentInterface {
|
||||||
|
resourceList: ResourceFhir[];
|
||||||
|
markForCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class GenericColumnDefn {
|
export class GenericColumnDefn {
|
||||||
title: string
|
title: string
|
||||||
prop?: string
|
prop?: string
|
||||||
|
@ -18,7 +26,7 @@ export class GenericColumnDefn {
|
||||||
templateUrl: './list-generic-resource.component.html',
|
templateUrl: './list-generic-resource.component.html',
|
||||||
styleUrls: ['./list-generic-resource.component.scss']
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
})
|
})
|
||||||
export class ListGenericResourceComponent implements OnInit {
|
export class ListGenericResourceComponent implements OnInit, ResourceListComponentInterface {
|
||||||
|
|
||||||
@Input() resourceList: ResourceFhir[] = []
|
@Input() resourceList: ResourceFhir[] = []
|
||||||
|
|
||||||
|
@ -32,9 +40,19 @@ export class ListGenericResourceComponent implements OnInit {
|
||||||
columns = []; //{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }
|
columns = []; //{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }
|
||||||
ColumnMode = ColumnMode;
|
ColumnMode = ColumnMode;
|
||||||
|
|
||||||
constructor() {}
|
constructor(public changeRef: ChangeDetectorRef) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
console.log("INIT CHILD")
|
||||||
|
|
||||||
|
this.renderList()
|
||||||
|
}
|
||||||
|
markForCheck(){
|
||||||
|
this.changeRef.markForCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
renderList(){
|
||||||
|
console.log("GENERIC RESOURCE INIT")
|
||||||
this.columns = this.columnDefinitions.map((defn) => {
|
this.columns = this.columnDefinitions.map((defn) => {
|
||||||
let column = {name: defn.title, prop: defn.title.replace(/[^A-Z0-9]/ig, "_")}
|
let column = {name: defn.title, prop: defn.title.replace(/[^A-Z0-9]/ig, "_")}
|
||||||
return column
|
return column
|
||||||
|
@ -44,10 +62,13 @@ export class ListGenericResourceComponent implements OnInit {
|
||||||
let row = {}
|
let row = {}
|
||||||
|
|
||||||
this.columnDefinitions.forEach((defn) => {
|
this.columnDefinitions.forEach((defn) => {
|
||||||
let resourceProp = defn.getter(resource.payload)
|
try{
|
||||||
let resourceFormatted = defn.format ? FORMATTERS[defn.format](resourceProp) : resourceProp
|
let resourceProp = defn.getter(resource.payload)
|
||||||
row[defn.title.replace(/[^A-Z0-9]/ig, "_")] = resourceFormatted
|
let resourceFormatted = defn.format ? FORMATTERS[defn.format](resourceProp) : resourceProp
|
||||||
//TODO: handle defaultValue
|
row[defn.title.replace(/[^A-Z0-9]/ig, "_")] = resourceFormatted
|
||||||
|
}catch (e){
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log("ROW:", row)
|
console.log("ROW:", row)
|
||||||
|
@ -55,6 +76,7 @@ export class ListGenericResourceComponent implements OnInit {
|
||||||
return row
|
return row
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-medication-administration',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListMedicationAdministrationComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Medication', versions: '*', format: 'code', getter: m => m.medicationCodeableConcept.coding[0] },
|
||||||
|
{ title: 'Route', versions: '*', format: 'code', getter: m => m.dosage.route.coding[0] },
|
||||||
|
{ title: 'Effective', versions: '*', getter: m => attributeXTime(m,'effective')},
|
||||||
|
{ title: 'Status', versions: '*', getter: m => m.status},
|
||||||
|
{ title: 'Status Reason', versions: '*', format: 'code', getter: m => m.statusReason[0].coding[0] },
|
||||||
|
{ title: 'Recorded', versions: '*', format: 'date', getter: m => m.extension.recorded }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-medication-dispense',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListMedicationDispenseComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Medication', versions: '*', format: 'code', getter: m => m.medicationCodeableConcept.coding[0] },
|
||||||
|
{ title: 'Handed Over Date', versions: '*', format: 'date', getter: m => m.whenHandedOver}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-nutrition-order',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListNutritionOrderComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Preference', versions: '*', format: 'code', getter: n => n.foodPreferenceModifier[0].coding[0] },
|
||||||
|
{ title: 'Exclusion', versions: '*', format: 'code', getter: n => n.excludeFoodModifier[0].coding[0] },
|
||||||
|
{ title: 'Date', versions: '*', format: 'date', getter: n => n.dateTime },
|
||||||
|
{ title: 'Status', versions: '*', getter: n => n.status }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {GenericColumnDefn, ListGenericResourceComponent} from './list-generic-resource.component';
|
||||||
|
import {attributeXTime} from './utils';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-service-request',
|
||||||
|
templateUrl: './list-generic-resource.component.html',
|
||||||
|
styleUrls: ['./list-generic-resource.component.scss']
|
||||||
|
})
|
||||||
|
export class ListServiceRequestComponent extends ListGenericResourceComponent {
|
||||||
|
columnDefinitions: GenericColumnDefn[] = [
|
||||||
|
{ title: 'Service', versions: '*', format: 'code', getter: s => s.code.coding[0] },
|
||||||
|
{ title: 'Author Date', versions: '*', format: 'date', getter: s => s.authoredOn },
|
||||||
|
{ title: 'Status', versions: '*', getter: s => s.status },
|
||||||
|
{ title: 'Reason', versions: '*', format: 'code', getter: s => s.reasonCode[0].coding[0] },
|
||||||
|
{ title: 'ID', versions: '*', getter: s => s.id },
|
||||||
|
{ title: 'Do Not Perform', versions: '*', getter: s => s.doNotPerform },
|
||||||
|
{ title: 'Reason Refused', versions: '*', format: 'code', getter: s => s.extension.reasonRefused.coding[0] }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h2 class="az-content-title mg-t-40">{{resourceListType}}</h2>
|
||||||
|
|
||||||
|
<ng-template resourceListOutlet></ng-template>
|
|
@ -1,18 +1,18 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { ListCarePlanComponent } from './list-care-plan.component';
|
import { ResourceListComponent } from './resource-list.component';
|
||||||
|
|
||||||
describe('ListCarePlanComponent', () => {
|
describe('ResourceListComponent', () => {
|
||||||
let component: ListCarePlanComponent;
|
let component: ResourceListComponent;
|
||||||
let fixture: ComponentFixture<ListCarePlanComponent>;
|
let fixture: ComponentFixture<ResourceListComponent>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [ ListCarePlanComponent ]
|
declarations: [ ResourceListComponent ]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(ListCarePlanComponent);
|
fixture = TestBed.createComponent(ResourceListComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
|
@ -0,0 +1,152 @@
|
||||||
|
import {ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, SimpleChanges, Type, ViewChild} from '@angular/core';
|
||||||
|
import {ResourceListOutletDirective} from '../../directive/resource-list-outlet.directive';
|
||||||
|
import {FastenApiService} from '../../services/fasten-api.service';
|
||||||
|
import {Source} from '../../models/fasten/source';
|
||||||
|
import {Observable, of} from 'rxjs';
|
||||||
|
import {ResourceFhir} from '../../models/fasten/resource_fhir';
|
||||||
|
import {ListAdverseEventComponent} from '../list-generic-resource/list-adverse-event.component';
|
||||||
|
import {ListCommunicationComponent} from '../list-generic-resource/list-communication.component';
|
||||||
|
import {ListConditionComponent} from '../list-generic-resource/list-condition.component';
|
||||||
|
import {ListCoverageComponent} from '../list-generic-resource/list-coverage.component';
|
||||||
|
import {ListDeviceRequestComponent} from '../list-generic-resource/list-device-request.component';
|
||||||
|
import {ListDocumentReferenceComponent} from '../list-generic-resource/list-document-reference.component';
|
||||||
|
import {ListEncounterComponent} from '../list-generic-resource/list-encounter.component';
|
||||||
|
import {ListImmunizationComponent} from '../list-generic-resource/list-immunization.component';
|
||||||
|
import {ListMedicationComponent} from '../list-generic-resource/list-medication.component';
|
||||||
|
import {ListMedicationAdministrationComponent} from '../list-generic-resource/list-medication-administration.component';
|
||||||
|
import {ListMedicationDispenseComponent} from '../list-generic-resource/list-medication-dispense.component';
|
||||||
|
import {ListMedicationRequestComponent} from '../list-generic-resource/list-medication-request.component';
|
||||||
|
import {ListNutritionOrderComponent} from '../list-generic-resource/list-nutrition-order.component';
|
||||||
|
import {ListObservationComponent} from '../list-generic-resource/list-observation.component';
|
||||||
|
import {ListProcedureComponent} from '../list-generic-resource/list-procedure.component';
|
||||||
|
import {ListServiceRequestComponent} from '../list-generic-resource/list-service-request.component';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
import {ResponseWrapper} from '../../models/response-wrapper';
|
||||||
|
import {ListGenericResourceComponent, ResourceListComponentInterface} from '../list-generic-resource/list-generic-resource.component';
|
||||||
|
import {ListCarePlanComponent} from '../list-generic-resource/list-care-plan.component';
|
||||||
|
import {ListAllergyIntoleranceComponent} from '../list-generic-resource/list-allergy-intolerance.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'source-resource-list',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
templateUrl: './resource-list.component.html',
|
||||||
|
styleUrls: ['./resource-list.component.scss']
|
||||||
|
})
|
||||||
|
export class ResourceListComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
|
@Input() source: Source;
|
||||||
|
@Input() resourceListType: string;
|
||||||
|
resourceListCache: { [name:string]: ResourceFhir[] } = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//location to dynamically load the resource list
|
||||||
|
@ViewChild(ResourceListOutletDirective, {static: true}) resourceListOutlet!: ResourceListOutletDirective;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private fastenApi: FastenApiService) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loadComponent()
|
||||||
|
}
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
this.loadComponent()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadComponent() {
|
||||||
|
//clear the current outlet
|
||||||
|
const viewContainerRef = this.resourceListOutlet.viewContainerRef;
|
||||||
|
viewContainerRef.clear();
|
||||||
|
|
||||||
|
this.getResources().subscribe((resourceList) => {
|
||||||
|
let componentType = this.typeLookup(this.resourceListType)
|
||||||
|
if(componentType != null){
|
||||||
|
console.log("Attempting to create component", this.resourceListType, componentType)
|
||||||
|
const componentRef = viewContainerRef.createComponent<ResourceListComponentInterface>(componentType);
|
||||||
|
componentRef.instance.resourceList = resourceList;
|
||||||
|
componentRef.instance.markForCheck()
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getResources(): Observable<ResourceFhir[]>{
|
||||||
|
|
||||||
|
if(!this.resourceListCache[this.resourceListType]){
|
||||||
|
// this resource type list has not been downloaded yet, do so now
|
||||||
|
|
||||||
|
return this.fastenApi.getResources(this.resourceListType, this.source.id)
|
||||||
|
.pipe(map((resourceList: ResourceFhir[]) => {
|
||||||
|
//cache this response so we can skip the request next time
|
||||||
|
this.resourceListCache[this.resourceListType] = resourceList
|
||||||
|
return resourceList
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
return of(this.resourceListCache[this.resourceListType])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeLookup(resourceType: string): Type<any> {
|
||||||
|
switch(resourceType) {
|
||||||
|
case "AllergyIntolerance": {
|
||||||
|
return ListAllergyIntoleranceComponent;
|
||||||
|
}
|
||||||
|
case "AdverseEvent": {
|
||||||
|
return ListAdverseEventComponent;
|
||||||
|
}
|
||||||
|
case "CarePlan": {
|
||||||
|
return ListCarePlanComponent;
|
||||||
|
}
|
||||||
|
case "Communication": {
|
||||||
|
return ListCommunicationComponent;
|
||||||
|
}
|
||||||
|
case "Condition": {
|
||||||
|
return ListConditionComponent;
|
||||||
|
}
|
||||||
|
case "Coverage": {
|
||||||
|
return ListCoverageComponent;
|
||||||
|
}
|
||||||
|
case "DeviceRequest": {
|
||||||
|
return ListDeviceRequestComponent;
|
||||||
|
}
|
||||||
|
case "DocumentReference": {
|
||||||
|
return ListDocumentReferenceComponent;
|
||||||
|
}
|
||||||
|
case "Encounter": {
|
||||||
|
return ListEncounterComponent;
|
||||||
|
}
|
||||||
|
case "Immunization": {
|
||||||
|
return ListImmunizationComponent;
|
||||||
|
}
|
||||||
|
case "Medication": {
|
||||||
|
return ListMedicationComponent;
|
||||||
|
}
|
||||||
|
case "MedicationAdministration": {
|
||||||
|
return ListMedicationAdministrationComponent;
|
||||||
|
}
|
||||||
|
case "MedicationDispense": {
|
||||||
|
return ListMedicationDispenseComponent;
|
||||||
|
}
|
||||||
|
case "MedicationRequest": {
|
||||||
|
return ListMedicationRequestComponent;
|
||||||
|
}
|
||||||
|
case "NutritionOrder": {
|
||||||
|
return ListNutritionOrderComponent;
|
||||||
|
}
|
||||||
|
case "Observation": {
|
||||||
|
return ListObservationComponent;
|
||||||
|
}
|
||||||
|
case "Procedure": {
|
||||||
|
return ListProcedureComponent;
|
||||||
|
}
|
||||||
|
case "ServiceRequest": {
|
||||||
|
return ListServiceRequestComponent;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
console.error("UNKNOWN COMPONENT TYPE", resourceType)
|
||||||
|
return null
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,58 +1,93 @@
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { ComponentsSidebarComponent } from './components-sidebar/components-sidebar.component';
|
import { ComponentsSidebarComponent } from './components-sidebar/components-sidebar.component';
|
||||||
|
import { ListExplanationOfBenefitComponent } from './list-explanation-of-benefit/list-explanation-of-benefit.component';
|
||||||
|
import { ListGenericResourceComponent,} from './list-generic-resource/list-generic-resource.component';
|
||||||
|
import { ListPatientComponent } from './list-patient/list-patient.component';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { UtilitiesSidebarComponent } from './utilities-sidebar/utilities-sidebar.component';
|
import { UtilitiesSidebarComponent } from './utilities-sidebar/utilities-sidebar.component';
|
||||||
import { ListPatientComponent } from './list-patient/list-patient.component';
|
|
||||||
import { ListExplanationOfBenefitComponent } from './list-explanation-of-benefit/list-explanation-of-benefit.component';
|
|
||||||
import { ListCarePlanComponent } from './list-care-plan/list-care-plan.component';
|
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import { ListGenericResourceComponent,} from './list-generic-resource/list-generic-resource.component';
|
import {ListAdverseEventComponent} from './list-generic-resource/list-adverse-event.component';
|
||||||
import {ListConditionComponent} from './list-generic-resource/list-condition.component'
|
import {ListConditionComponent} from './list-generic-resource/list-condition.component'
|
||||||
import {ListEncounterComponent} from './list-generic-resource/list-encounter.component'
|
import {ListEncounterComponent} from './list-generic-resource/list-encounter.component'
|
||||||
|
import {ListImmunizationComponent} from './list-generic-resource/list-immunization.component'
|
||||||
|
import {ListMedicationAdministrationComponent} from './list-generic-resource/list-medication-administration.component';
|
||||||
import {ListMedicationComponent} from './list-generic-resource/list-medication.component'
|
import {ListMedicationComponent} from './list-generic-resource/list-medication.component'
|
||||||
|
import {ListMedicationDispenseComponent} from './list-generic-resource/list-medication-dispense.component';
|
||||||
|
import {ListMedicationRequestComponent} from './list-generic-resource/list-medication-request.component'
|
||||||
|
import {ListNutritionOrderComponent} from './list-generic-resource/list-nutrition-order.component';
|
||||||
import {ListObservationComponent} from './list-generic-resource/list-observation.component'
|
import {ListObservationComponent} from './list-generic-resource/list-observation.component'
|
||||||
import {ListProcedureComponent} from './list-generic-resource/list-procedure.component'
|
import {ListProcedureComponent} from './list-generic-resource/list-procedure.component'
|
||||||
import {ListImmunizationComponent} from './list-generic-resource/list-immunization.component'
|
import {ListCommunicationComponent} from './list-generic-resource/list-communication.component';
|
||||||
import {ListMedicationRequestComponent} from './list-generic-resource/list-medication-request.component'
|
import {ListDeviceRequestComponent} from './list-generic-resource/list-device-request.component';
|
||||||
|
import {ListCoverageComponent} from './list-generic-resource/list-coverage.component';
|
||||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
import {ListServiceRequestComponent} from './list-generic-resource/list-service-request.component';
|
||||||
|
import {ListDocumentReferenceComponent} from './list-generic-resource/list-document-reference.component';
|
||||||
|
import { ResourceListComponent } from './resource-list/resource-list.component';
|
||||||
|
import {ResourceListOutletDirective} from '../directive/resource-list-outlet.directive';
|
||||||
|
import {ListCarePlanComponent} from './list-generic-resource/list-care-plan.component';
|
||||||
|
import {ListAllergyIntoleranceComponent} from './list-generic-resource/list-allergy-intolerance.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
NgxDatatableModule
|
NgxDatatableModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
ComponentsSidebarComponent,
|
ComponentsSidebarComponent,
|
||||||
UtilitiesSidebarComponent,
|
UtilitiesSidebarComponent,
|
||||||
ListPatientComponent,
|
ListAllergyIntoleranceComponent,
|
||||||
ListObservationComponent,
|
ListAdverseEventComponent,
|
||||||
ListExplanationOfBenefitComponent,
|
|
||||||
ListImmunizationComponent,
|
|
||||||
ListEncounterComponent,
|
|
||||||
ListCarePlanComponent,
|
ListCarePlanComponent,
|
||||||
ListGenericResourceComponent,
|
ListCommunicationComponent,
|
||||||
ListMedicationComponent,
|
|
||||||
ListProcedureComponent,
|
|
||||||
ListConditionComponent,
|
ListConditionComponent,
|
||||||
ListMedicationRequestComponent
|
ListEncounterComponent,
|
||||||
|
ListExplanationOfBenefitComponent,
|
||||||
|
ListGenericResourceComponent,
|
||||||
|
ListImmunizationComponent,
|
||||||
|
ListMedicationAdministrationComponent,
|
||||||
|
ListMedicationComponent,
|
||||||
|
ListMedicationDispenseComponent,
|
||||||
|
ListMedicationRequestComponent,
|
||||||
|
ListNutritionOrderComponent,
|
||||||
|
ListObservationComponent,
|
||||||
|
ListPatientComponent,
|
||||||
|
ListDeviceRequestComponent,
|
||||||
|
ListProcedureComponent,
|
||||||
|
ListCoverageComponent,
|
||||||
|
ListServiceRequestComponent,
|
||||||
|
ListDocumentReferenceComponent,
|
||||||
|
ResourceListComponent,
|
||||||
|
ResourceListOutletDirective,
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
ComponentsSidebarComponent,
|
ComponentsSidebarComponent,
|
||||||
UtilitiesSidebarComponent,
|
ListAllergyIntoleranceComponent,
|
||||||
ListPatientComponent,
|
ListAdverseEventComponent,
|
||||||
ListExplanationOfBenefitComponent,
|
ListCarePlanComponent,
|
||||||
ListImmunizationComponent,
|
ListCommunicationComponent,
|
||||||
ListEncounterComponent,
|
ListConditionComponent,
|
||||||
ListCarePlanComponent,
|
ListEncounterComponent,
|
||||||
ListGenericResourceComponent,
|
ListExplanationOfBenefitComponent,
|
||||||
ListMedicationComponent,
|
ListGenericResourceComponent,
|
||||||
ListObservationComponent,
|
ListImmunizationComponent,
|
||||||
ListProcedureComponent,
|
ListMedicationAdministrationComponent,
|
||||||
ListConditionComponent,
|
ListMedicationComponent,
|
||||||
ListMedicationRequestComponent
|
ListMedicationDispenseComponent,
|
||||||
|
ListMedicationRequestComponent,
|
||||||
|
ListNutritionOrderComponent,
|
||||||
|
ListObservationComponent,
|
||||||
|
ListPatientComponent,
|
||||||
|
ListProcedureComponent,
|
||||||
|
ListDeviceRequestComponent,
|
||||||
|
UtilitiesSidebarComponent,
|
||||||
|
ListCoverageComponent,
|
||||||
|
ListServiceRequestComponent,
|
||||||
|
ListDocumentReferenceComponent,
|
||||||
|
ResourceListComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { ResourceListOutletDirective } from './resource-list-outlet.directive';
|
||||||
|
|
||||||
|
describe('ResourceListOutletDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
const directive = new ResourceListOutletDirective();
|
||||||
|
expect(directive).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
import {Directive, ViewContainerRef} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[resourceListOutlet]'
|
||||||
|
})
|
||||||
|
export class ResourceListOutletDirective {
|
||||||
|
|
||||||
|
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import {Source} from './source';
|
||||||
|
|
||||||
|
export class ResourceTypeCounts {
|
||||||
|
count: number
|
||||||
|
source_id: string
|
||||||
|
resource_type: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SourceSummary {
|
||||||
|
source: Source
|
||||||
|
resource_type_counts: ResourceTypeCounts[]
|
||||||
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="az-content-left">
|
<div class="az-content-left">
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li *ngFor="let resourceGroup of resourcesGroupedByType | keyvalue" (click)="selectResourceType(resourceGroup.key)" class="list-group-item d-flex justify-content-between align-items-center">
|
<li *ngFor="let resourceGroup of resourceTypeCounts | keyvalue" (click)="selectResourceType(resourceGroup.key)" class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
{{resourceGroup.key}} <span class="badge badge-primary badge-pill">{{resourceGroup.value.length}}</span>
|
{{resourceGroup.key}} <span class="badge badge-primary badge-pill">{{resourceGroup.value}}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,16 +14,7 @@
|
||||||
<span>Details</span>
|
<span>Details</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="az-content-title mg-t-40">{{selectedResourceType}}</h2>
|
<source-resource-list [source]="selectedSource" [resourceListType]="selectedResourceType"></source-resource-list>
|
||||||
|
|
||||||
<app-list-condition *ngIf="selectedResourceType == 'Condition'" [resourceList]="selectedResources"></app-list-condition>
|
|
||||||
<app-list-care-plan *ngIf="selectedResourceType == 'CarePlan'" [resourceList]="selectedResources"></app-list-care-plan>
|
|
||||||
<app-list-encounter *ngIf="selectedResourceType == 'Encounter'" [resourceList]="selectedResources"></app-list-encounter>
|
|
||||||
<app-list-immunization *ngIf="selectedResourceType == 'Immunization'" [resourceList]="selectedResources"></app-list-immunization>
|
|
||||||
<app-list-medication *ngIf="selectedResourceType == 'Medication'" [resourceList]="selectedResources"></app-list-medication>
|
|
||||||
<app-list-medication-request *ngIf="selectedResourceType == 'MedicationRequest'" [resourceList]="selectedResources"></app-list-medication-request>
|
|
||||||
<app-list-observation *ngIf="selectedResourceType == 'Observation'" [resourceList]="selectedResources"></app-list-observation>
|
|
||||||
<app-list-procedure *ngIf="selectedResourceType == 'Procedure'" [resourceList]="selectedResources"></app-list-procedure>
|
|
||||||
|
|
||||||
</div><!-- az-content-body -->
|
</div><!-- az-content-body -->
|
||||||
</div><!-- container -->
|
</div><!-- container -->
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {Source} from '../../models/fasten/source';
|
import {Source} from '../../models/fasten/source';
|
||||||
import {FastenApiService} from '../../services/fasten-api.service';
|
import {FastenApiService} from '../../services/fasten-api.service';
|
||||||
|
import {ResourceListOutletDirective} from '../../directive/resource-list-outlet.directive';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -13,9 +14,8 @@ export class SourceDetailComponent implements OnInit {
|
||||||
|
|
||||||
selectedSource: Source = null
|
selectedSource: Source = null
|
||||||
selectedResourceType: string = null
|
selectedResourceType: string = null
|
||||||
selectedResources: any[] = []
|
|
||||||
|
|
||||||
resourcesGroupedByType: { [name: string]: any[] } = {}
|
resourceTypeCounts: { [name: string]: number } = {}
|
||||||
|
|
||||||
constructor(private fastenApi: FastenApiService, private router: Router, private route: ActivatedRoute) {
|
constructor(private fastenApi: FastenApiService, private router: Router, private route: ActivatedRoute) {
|
||||||
//check if the current Source was sent over using the router state storage:
|
//check if the current Source was sent over using the router state storage:
|
||||||
|
@ -25,26 +25,16 @@ export class SourceDetailComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.selectedSource == null) {
|
//always request the source summary
|
||||||
//lookup the source by ID.
|
this.fastenApi.getSourceSummary(this.route.snapshot.paramMap.get('source_id')).subscribe((sourceSummary) => {
|
||||||
this.fastenApi.getSource(this.route.snapshot.paramMap.get('source_id')).subscribe((source) => {
|
this.selectedSource = sourceSummary.source;
|
||||||
this.selectedSource = source;
|
for(let resourceTypeCount of sourceSummary.resource_type_counts){
|
||||||
});
|
this.resourceTypeCounts[resourceTypeCount.resource_type] = resourceTypeCount.count
|
||||||
}
|
}
|
||||||
|
});
|
||||||
this.fastenApi.getResources(undefined, this.route.snapshot.paramMap.get('source_id')).subscribe((resourceList) => {
|
|
||||||
console.log("RESOURCES", resourceList)
|
|
||||||
let _resourcesGroupedByType = this.resourcesGroupedByType
|
|
||||||
resourceList.forEach(resource => {
|
|
||||||
let resourceTypeList = _resourcesGroupedByType[resource.source_resource_type] || [];
|
|
||||||
resourceTypeList.push(resource)
|
|
||||||
_resourcesGroupedByType[resource.source_resource_type] = resourceTypeList
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectResourceType(resourceType: string) {
|
selectResourceType(resourceType: string) {
|
||||||
this.selectedResourceType = resourceType
|
this.selectedResourceType = resourceType
|
||||||
this.selectedResources = this.resourcesGroupedByType[resourceType]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {ResponseWrapper} from '../models/response-wrapper';
|
||||||
import {Source} from '../models/fasten/source';
|
import {Source} from '../models/fasten/source';
|
||||||
import {User} from '../models/fasten/user';
|
import {User} from '../models/fasten/user';
|
||||||
import {ResourceFhir} from '../models/fasten/resource_fhir';
|
import {ResourceFhir} from '../models/fasten/resource_fhir';
|
||||||
|
import {SourceSummary} from '../models/fasten/source-summary';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -110,6 +111,16 @@ export class FastenApiService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSourceSummary(sourceId: string): Observable<SourceSummary> {
|
||||||
|
return this._httpClient.get<any>(`${this.getBasePath()}/api/secure/source/${sourceId}/summary`)
|
||||||
|
.pipe(
|
||||||
|
map((response: ResponseWrapper) => {
|
||||||
|
console.log("SOURCE RESPONSE", response)
|
||||||
|
return response.data as SourceSummary
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getResources(sourceResourceType?: string, sourceID?: string): Observable<ResourceFhir[]> {
|
getResources(sourceResourceType?: string, sourceID?: string): Observable<ResourceFhir[]> {
|
||||||
let queryParams = {}
|
let queryParams = {}
|
||||||
if(sourceResourceType){
|
if(sourceResourceType){
|
||||||
|
|
Loading…
Reference in New Issue