Skip to content

Commit

Permalink
sort all resources by "sort_date" column during query
Browse files Browse the repository at this point in the history
return units when querying
rename all usages of "source" page to "explore"
adding new explore page.
fix dashboard widgets to correctly
  • Loading branch information
AnalogJ committed Aug 9, 2023
1 parent 28cb918 commit 0397a2f
Show file tree
Hide file tree
Showing 30 changed files with 252 additions and 45 deletions.
1 change: 1 addition & 0 deletions backend/pkg/database/sqlite_repository_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func (sr *SqliteRepository) QueryResources(ctx context.Context, query models.Que
Select(fmt.Sprintf("%s.*", TABLE_ALIAS)).
Where(strings.Join(whereClauses, " AND "), whereNamedParameters).
Group(fmt.Sprintf("%s.id", TABLE_ALIAS)).
Order(fmt.Sprintf("%s.sort_date asc", TABLE_ALIAS)).
Table(strings.Join(fromClauses, ", ")).
Find(&results)

Expand Down
8 changes: 6 additions & 2 deletions backend/pkg/web/handler/dashboard/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"q": {
"select": [
"valueQuantity.value as data",
"valueQuantity.unit as unit",
"(effectiveDateTime | issued).first() as label"
],
"from": "Observation",
Expand All @@ -50,6 +51,7 @@
"q": {
"select": [
"valueQuantity.value as data",
"valueQuantity.unit as unit",
"(effectiveDateTime | issued).first() as label"
],
"from": "Observation",
Expand All @@ -75,7 +77,8 @@
{
"q": {
"select": [
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8462-4').valueQuantity.value as data"
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8462-4').valueQuantity.value as data",
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8462-4').valueQuantity.unit as unit"
],
"from": "Observation",
"where": {
Expand All @@ -89,7 +92,8 @@
{
"q": {
"select": [
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8480-6').valueQuantity.value as data"
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8480-6').valueQuantity.value as data",
"component.where(code.coding.system = 'http://loinc.org' and code.coding.code = '8480-6').valueQuantity.unit as unit"
],
"from": "Observation",
"where": {
Expand Down
11 changes: 8 additions & 3 deletions frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {PatientProfileComponent} from './pages/patient-profile/patient-profile.c
import {MedicalHistoryComponent} from './pages/medical-history/medical-history.component';
import {ReportLabsComponent} from './pages/report-labs/report-labs.component';
import {ResourceCreatorComponent} from './pages/resource-creator/resource-creator.component';
import {ExploreComponent} from './pages/explore/explore.component';

const routes: Routes = [

Expand All @@ -23,9 +24,13 @@ const routes: Routes = [

{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'source/:source_id', component: SourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'source/:source_id/resource/:resource_id', component: ResourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'source/:source_id/resource/:resource_type/:resource_id', component: ResourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },

//explore page will replace source/* pages
{ path: 'explore', component: ExploreComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'explore/:source_id', component: SourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'explore/:source_id/resource/:resource_id', component: ResourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'explore/:source_id/resource/:resource_type/:resource_id', component: ResourceDetailComponent, canActivate: [ IsAuthenticatedAuthGuard] },

{ path: 'sources', component: MedicalSourcesComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'sources/callback/:source_type', component: MedicalSourcesComponent, canActivate: [ IsAuthenticatedAuthGuard] },
{ path: 'resource/create', component: ResourceCreatorComponent, canActivate: [ IsAuthenticatedAuthGuard] },
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { NgSelectModule } from '@ng-select/ng-select';
import {HTTP_CLIENT_TOKEN} from "./dependency-injection";
import {WidgetsModule} from './widgets/widgets.module';
import { ExploreComponent } from './pages/explore/explore.component';

@NgModule({
declarations: [
Expand All @@ -50,6 +51,7 @@ import {WidgetsModule} from './widgets/widgets.module';
MedicalHistoryComponent,
ReportLabsComponent,
ResourceCreatorComponent,
ExploreComponent,
],
imports: [
FormsModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<fhir-coding *ngFor="let coding of rowItem.data" [coding]="coding"></fhir-coding>
</ng-template>
<ng-template #dataTypeReference>
<a routerLink="/source/{{displayModel.source_id}}/resource/{{rowItem.data.reference}}">{{rowItem.data.display}}</a>
<a routerLink="/explore/{{displayModel.source_id}}/resource/{{rowItem.data.reference}}">{{rowItem.data.display}}</a>
</ng-template>
<ng-template #dataTypeString>{{rowItem.data}}</ng-template>
</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ <h6 class="card-title">{{displayModel?.title}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h6 class="card-title">{{displayModel?.title}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ <h6 class="card-title">{{displayModel?.category?.text}}</h6>
</div>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ <h6 class="card-title">{{displayModel?.title}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ <h6 class="card-title">{{displayModel?.sort_title}}</h6>
</div>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h6 class="card-title">{{displayModel?.display}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h6 class="card-title">{{displayModel?.title?.display}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ <h6 class="card-title">{{displayModel?.sort_title}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h6 class="card-title">{{displayModel?.display}}</h6>
<fhir-ui-table [displayModel]="displayModel" [tableData]="tableData"></fhir-ui-table>
</div>
<div *ngIf="showDetails" class="card-footer">
<a class="float-right" routerLink="/source/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
<a class="float-right" routerLink="/explore/{{displayModel?.source_id}}/resource/{{displayModel?.source_resource_id}}">details</a>
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="row" >
<!-- Condition Header -->
<div class="col-6">
<span routerLink="/source/{{firstObservation?.source_id}}/resource/{{firstObservation?.source_resource_id}}">{{observationTitle}}</span>
<span routerLink="/explore/{{firstObservation?.source_id}}/resource/{{firstObservation?.source_resource_id}}">{{observationTitle}}</span>
</div>
<div class="col-6">
{{firstObservation | fhirPath: "Observation.effectiveDateTime": "Observation.issued" | date}}
Expand Down Expand Up @@ -36,7 +36,7 @@
<div #collapse="ngbCollapse" [ngbCollapse]="true">

<ul>
<li class="cursor-pointer tx-indigo" *ngFor="let observation of observations" routerLink="/source/{{observation?.source_id}}/resource/{{observation?.source_resource_id}}">Observation: {{observation | fhirPath: "Observation.effectiveDateTime": "Observation.issued" | date}}</li>
<li class="cursor-pointer tx-indigo" *ngFor="let observation of observations" routerLink="/explore/{{observation?.source_id}}/resource/{{observation?.source_resource_id}}">Observation: {{observation | fhirPath: "Observation.effectiveDateTime": "Observation.issued" | date}}</li>
</ul>
</div>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/pages/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class DashboardComponent implements OnInit {
}

selectSource(selectedSource: Source){
this.router.navigateByUrl(`/source/${selectedSource.id}`, {
this.router.navigateByUrl(`/explore/${selectedSource.id}`, {
state: selectedSource
});
}
Expand Down
73 changes: 73 additions & 0 deletions frontend/src/app/pages/explore/explore.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<div class="az-content">
<div class="container">
<div class="az-content-body pd-lg-l-40 d-flex flex-column">

<!-- Header Row -->
<report-header [reportHeaderTitle]="'Explore'" [reportHeaderSubTitle]="'Explore your Medical Records'"></report-header>

<ng-container [ngTemplateOutlet]="loading ? isLoadingTemplate : (connectedSources.length == 0) ? emptyReport : report"></ng-container>

<ng-template #report>
<div class="row">
<app-medical-sources-card class="col-sm-3 mg-b-20 px-3"
*ngFor="let sourceData of connectedSources"
[sourceInfo]="sourceData"
(onClick)="exploreSource($event)"
></app-medical-sources-card>
</div>
</ng-template>

<ng-template #emptyReport>
<div class="d-flex align-items-center" style="height:100%">
<div class="modal-body tx-center pd-y-20 pd-x-20">
<h4 class="tx-purple mg-b-20">No Sources Found!</h4>
<p class="mg-b-20 mg-x-20">
Fasten was unable to find any connected sources. You will need to connect a medical source before you can use this page.
</p>
<p class="mg-b-20 mg-x-20">
Click below to add a new healthcare provider to Fasten.
</p>
<button [routerLink]="'/sources'" type="button" class="btn btn-purple pd-x-25">Add Source</button>
<button [routerLink]="'/resource/create'" type="button" class="btn btn-purple mg-l-10 pd-x-25">Add Condition</button>

</div><!-- modal-body -->
</div>
</ng-template>

<ng-template #isLoadingTemplate>
<div class="row">
<div class="col-12">
<app-loading-spinner [loadingTitle]="'Please wait, loading report...'"></app-loading-spinner>
</div>
</div>
</ng-template>

<ng-template #contentModalRef let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title"></h4>
<button type="button" class="btn btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>

<div class="modal-body">
<h6>Manage Source</h6>
<p>Existing connections can be "Synced", "Reconnected" or "Deleted"</p>
<ul>
<li><p><strong>Sync</strong> - Download all resources from this healthcare provider, storing them securely in Fasten</p></li>
<li><p><strong>Reconnect</strong> - If your healthcare connection has expired, you can use this button to reconnect</p></li>
<li><p><strong>Delete</strong> - Delete all resources for this healthcare provider. This will ONLY effect data stored in Fasten</p></li>
</ul>
</div>

<div class="modal-footer">
<!-- <button (click)="sourceSyncHandler(modalSelectedSourceListItem.source)" type="button" class="btn btn-indigo">Sync</button>-->
<!-- <button (click)="connectHandler($event, modalSelectedSourceListItem.source['source_type'])" type="button" class="btn btn-outline-light">Reconnect</button>-->
<button type="button" class="btn disabled btn-outline-danger">Delete</button>
<button (click)="modal.dismiss('Close click')" type="button" class="btn btn-outline-light">Close</button>
</div>
</ng-template>

</div>
</div>
</div>
Empty file.
23 changes: 23 additions & 0 deletions frontend/src/app/pages/explore/explore.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ExploreComponent } from './explore.component';

describe('ExploreComponent', () => {
let component: ExploreComponent;
let fixture: ComponentFixture<ExploreComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ExploreComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(ExploreComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
62 changes: 62 additions & 0 deletions frontend/src/app/pages/explore/explore.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Component, OnInit } from '@angular/core';
import {FastenApiService} from '../../services/fasten-api.service';
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {Source} from '../../models/fasten/source';
import {forkJoin} from 'rxjs';
import {LighthouseService} from '../../services/lighthouse.service';
import {SourceListItem} from '../medical-sources/medical-sources.component';
import {Router} from '@angular/router';

@Component({
selector: 'app-explore',
templateUrl: './explore.component.html',
styleUrls: ['./explore.component.scss']
})
export class ExploreComponent implements OnInit {
loading: boolean = false
connectedSources: SourceListItem[] = []
constructor(
private fastenApi: FastenApiService,
private lighthouseApi: LighthouseService,
private router: Router
) { }

ngOnInit(): void {
this.loading = true
this.fastenApi.getSources().subscribe(results => {
this.loading = false

//handle connected sources sources
const connectedSources = results as Source[]
forkJoin(connectedSources.map((source) => this.lighthouseApi.getLighthouseSource(source.source_type))).subscribe((connectedMetadata) => {
for(const ndx in connectedSources){
this.connectedSources.push({source: connectedSources[ndx], metadata: connectedMetadata[ndx]})
}
})
}, error => {
this.loading = false
})

}

public exploreSource(sourceListItem: SourceListItem, ) {
this.router.navigateByUrl(`/source/${sourceListItem.source.id}`, {
state: sourceListItem.source
});

// if(this.status[sourceListItem.metadata.source_type] || !sourceListItem.source){
// //if this source is currently "loading" dont open the modal window
// return
// }
//
// this.modalSelectedSourceListItem = sourceListItem
// this.modalService.open(contentModalRef, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
// this.modalSelectedSourceListItem = null
// this.modalCloseResult = `Closed with: ${result}`;
// }, (reason) => {
// this.modalSelectedSourceListItem = null
// this.modalCloseResult = `Dismissed ${this.getDismissReason(reason)}`;
// });
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="container">
<div class="az-content-body">
<div class="az-content-breadcrumb">
<span class="cursor-pointer" routerLink="/source/{{sourceId}}">{{sourceName}}</span>
<span class="cursor-pointer" routerLink="/explore/{{sourceId}}">{{sourceName}}</span>
<span>Resource</span>
<span>{{resource?.source_resource_type}}</span>
<span>{{resource?.source_resource_id}}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<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">
<a routerLink="/explore/{{selectedSource?.id}}/resource/{{selectedPatient?.source_resource_id}}" class="btn btn-indigo btn-icon float-right">
<i class="fas fa-info-circle"></i>
</a>
</div>
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/app/pipes/dataset-latest-entry.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DatasetLatestEntryPipe } from './dataset-latest-entry.pipe';

describe('DatasetLatestEntryPipe', () => {
it('create an instance', () => {
const pipe = new DatasetLatestEntryPipe();
expect(pipe).toBeTruthy();
});
});
Loading

0 comments on commit 0397a2f

Please sign in to comment.