Skip to content

Commit

Permalink
Merge pull request #223 from fastenhealth/paginate_graph
Browse files Browse the repository at this point in the history
  • Loading branch information
AnalogJ authored Oct 4, 2023
2 parents 9c5bf15 + 900218e commit 877a132
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 66 deletions.
2 changes: 1 addition & 1 deletion backend/pkg/database/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type DatabaseRepository interface {
AddResourceAssociation(ctx context.Context, source *models.SourceCredential, resourceType string, resourceId string, relatedSource *models.SourceCredential, relatedResourceType string, relatedResourceId string) error
RemoveResourceAssociation(ctx context.Context, source *models.SourceCredential, resourceType string, resourceId string, relatedSource *models.SourceCredential, relatedResourceType string, relatedResourceId string) error
FindResourceAssociationsByTypeAndId(ctx context.Context, source *models.SourceCredential, resourceType string, resourceId string) ([]models.RelatedResource, error)
GetFlattenedResourceGraph(ctx context.Context, graphType pkg.ResourceGraphType) (map[string][]*models.ResourceBase, error)
GetFlattenedResourceGraph(ctx context.Context, graphType pkg.ResourceGraphType, options models.ResourceGraphOptions) (map[string][]*models.ResourceBase, *models.ResourceGraphMetadata, error)
AddResourceComposition(ctx context.Context, compositionTitle string, resources []*models.ResourceBase) error
//UpsertProfile(context.Context, *models.Profile) error
//UpsertOrganziation(context.Context, *models.Organization) error
Expand Down
15 changes: 8 additions & 7 deletions backend/pkg/database/sqlite_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ func (sr *SqliteRepository) GetUserByUsername(ctx context.Context, username stri
return &foundUser, result.Error
}

// TODO: check for error, right now we return a nil which may cause a panic.
//TODO: check for error, right now we return a nil which may cause a panic.
//TODO: can we cache the current user? //SECURITY:
func (sr *SqliteRepository) GetCurrentUser(ctx context.Context) (*models.User, error) {
username := ctx.Value(pkg.ContextKeyTypeAuthUsername)
if username == nil {
Expand Down Expand Up @@ -446,6 +447,7 @@ func (sr *SqliteRepository) ListResources(ctx context.Context, queryOptions mode
}
}

//TODO: should this be deprecated? (replaced by ListResources)
func (sr *SqliteRepository) GetResourceByResourceTypeAndId(ctx context.Context, sourceResourceType string, sourceResourceId string) (*models.ResourceBase, error) {
currentUser, currentUserErr := sr.GetCurrentUser(ctx)
if currentUserErr != nil {
Expand Down Expand Up @@ -635,14 +637,13 @@ func (sr *SqliteRepository) FindResourceAssociationsByTypeAndId(ctx context.Cont
// - find source for each resource
// - (SECURITY) ensure the current user and the source for each resource matches
// - check if there is a Composition resource Type already.
// - if Composition type already exists:
// - update "relatesTo" field with additional data.
// - else:
// - Create a Composition resource type (populated with "relatesTo" references to all provided Resources)
//
// - if Composition type already exists:
// - update "relatesTo" field with additional data.
// - else:
// - Create a Composition resource type (populated with "relatesTo" references to all provided Resources)
// - add AddResourceAssociation for all resources linked to the Composition resource
// - store the Composition resource
// TODO: determine if we should be using a List Resource instead of a Composition resource
//TODO: determine if we should be using a List Resource instead of a Composition resource
func (sr *SqliteRepository) AddResourceComposition(ctx context.Context, compositionTitle string, resources []*models.ResourceBase) error {
currentUser, currentUserErr := sr.GetCurrentUser(ctx)
if currentUserErr != nil {
Expand Down
218 changes: 181 additions & 37 deletions backend/pkg/database/sqlite_repository_graph.go

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions backend/pkg/models/resource_graph_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package models

type ResourceGraphMetadata struct {
TotalElements int `json:"total_elements"`
PageSize int `json:"page_size"`
Page int `json:"page"`
}
5 changes: 5 additions & 0 deletions backend/pkg/models/resource_graph_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package models

type ResourceGraphOptions struct {
Page int
}
16 changes: 16 additions & 0 deletions backend/pkg/utils/paginate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package utils

import "github.com/fastenhealth/fasten-onprem/backend/pkg/models"

func PaginateResourceList(resourceList []models.ResourceBase, skip int, size int) []models.ResourceBase {
if skip > len(resourceList) {
skip = len(resourceList)
}

end := skip + size
if end > len(resourceList) {
end = len(resourceList)
}

return resourceList[skip:end]
}
18 changes: 16 additions & 2 deletions backend/pkg/web/handler/resource_fhir.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,26 @@ func GetResourceFhirGraph(c *gin.Context) {

graphType := strings.Trim(c.Param("graphType"), "/")

resourceListDictionary, err := databaseRepo.GetFlattenedResourceGraph(c, pkg.ResourceGraphType(graphType))
graphOptions := models.ResourceGraphOptions{}
if len(c.Query("page")) > 0 {
pageNumb, err := strconv.Atoi(c.Query("page"))
if err != nil {
logger.Errorln("An error occurred while calculating page number", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
graphOptions.Page = pageNumb
}

resourceListDictionary, resourceListMetadata, err := databaseRepo.GetFlattenedResourceGraph(c, pkg.ResourceGraphType(graphType), graphOptions)
if err != nil {
logger.Errorln("An error occurred while retrieving list of resources", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}

c.JSON(http.StatusOK, gin.H{"success": true, "data": resourceListDictionary})
c.JSON(http.StatusOK, gin.H{"success": true, "data": map[string]interface{}{
"results": resourceListDictionary,
"metadata": resourceListMetadata,
}})
}
12 changes: 12 additions & 0 deletions frontend/src/app/models/fasten/resource-graph-response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {ResourceFhir} from './resource_fhir';

export class ResourceGraphResponse {
results: {[resource_type: string]: ResourceFhir[]}
metadata: ResourceGraphMetadata
}

export class ResourceGraphMetadata {
total_elements: number
page_size: number
page: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<div class="row mt-5 mb-3">
<div class="col-12">

<div class="alert alert-warning" role="alert">
<div [hidden]="true" class="alert alert-warning" role="alert">
<strong>Warning!</strong> Fasten has detected medical Encounters that are not associated with a Condition.
They are grouped under the "Unassigned" section below.
<br/>
Expand All @@ -34,6 +34,18 @@ <h1 class="az-dashboard-title">Condition</h1>
<!-- Condition List -->
<app-report-medical-history-condition *ngFor="let condition of conditions; let i = index" [conditionGroup]="condition"></app-report-medical-history-condition>
<app-report-medical-history-explanation-of-benefit *ngFor="let eob of explanationOfBenefits; let i = index" [explanationOfBenefitGroup]="eob"></app-report-medical-history-explanation-of-benefit>

<div class="row">
<div class="col-12 d-flex justify-content-center flex-nowrap">
<ngb-pagination
*ngIf="resourceGraphMetadata.total_elements > resourceGraphMetadata.page_size"
[(page)]="resourceGraphMetadata.page"
(pageChange)="pageChange($event)"
[pageSize]="resourceGraphMetadata.page_size"
[collectionSize]="resourceGraphMetadata.total_elements"></ngb-pagination>
</div>
</div>

</ng-template>

<ng-template #emptyReport>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {ResourceFhir} from '../../models/fasten/resource_fhir';
import { ModalDismissReasons, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {ReportMedicalHistoryEditorComponent} from '../../components/report-medical-history-editor/report-medical-history-editor.component';
import {forkJoin} from 'rxjs';
import {ResourceGraphMetadata, ResourceGraphResponse} from '../../models/fasten/resource-graph-response';
// import {ReportEditorRelatedComponent} from '../../components/report-editor-related/report-editor-related.component';

@Component({
Expand All @@ -21,19 +22,34 @@ export class MedicalHistoryComponent implements OnInit {
unassigned_encounters: ResourceFhir[] = []
resourceLookup: {[name: string]: ResourceFhir} = {}

resourceGraphMetadata: ResourceGraphMetadata = {
total_elements: 0,
page_size: 0,
page: 1
}

constructor(
private fastenApi: FastenApiService,
private modalService: NgbModal
) { }


ngOnInit(): void {
//load the first page
this.pageChange(1)
}

pageChange(page: number){
this.loading = true
this.fastenApi.getResourceGraph().subscribe(results => {
this.fastenApi.getResourceGraph(null, page).subscribe((response: ResourceGraphResponse) => {
this.loading = false
this.conditions = [].concat(results["Condition"] || [], results["Composition"] || [])
this.unassigned_encounters = results["Encounter"] || []
this.explanationOfBenefits = results["ExplanationOfBenefit"] || []
this.resourceGraphMetadata = response.metadata
//page counter is 1 indexed but the backend is 0 indexed
this.resourceGraphMetadata.page = this.resourceGraphMetadata.page + 1

this.conditions = [].concat(response.results["Condition"] || [], response.results["Composition"] || [])
this.unassigned_encounters = response.results["Encounter"] || []
this.explanationOfBenefits = response.results["ExplanationOfBenefit"] || []

//populate a lookup table with all resources
for(let condition of this.conditions){
Expand Down Expand Up @@ -66,6 +82,7 @@ export class MedicalHistoryComponent implements OnInit {

}


openEditorRelated(): void {
const modalRef = this.modalService.open(ReportMedicalHistoryEditorComponent, {
size: 'xl',
Expand Down
19 changes: 11 additions & 8 deletions frontend/src/app/pages/report-labs/report-labs.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,17 @@ <h1 class="az-dashboard-title">Observations</h1>


<!-- Pagination -->
<ngb-pagination
class="mr-auto"
[collectionSize]="allObservationGroups.length"
[(page)]="currentPage"
[pageSize]="pageSize"
(pageChange)="populateObservationsForCurrentPage()"
>
</ngb-pagination>
<div class="row">
<div class="col-12 d-flex justify-content-center flex-nowrap">
<ngb-pagination
[collectionSize]="allObservationGroups.length"
[(page)]="currentPage"
[pageSize]="pageSize"
(pageChange)="populateObservationsForCurrentPage()"
>
</ngb-pagination>
</div>
</div>

</ng-template>

Expand Down
12 changes: 9 additions & 3 deletions frontend/src/app/services/fasten-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import * as fhirpath from 'fhirpath';
import _ from 'lodash';
import {DashboardConfig} from '../models/widget/dashboard-config';
import {DashboardWidgetQuery} from '../models/widget/dashboard-widget-query';
import {ResourceGraphResponse} from '../models/fasten/resource-graph-response';
import { fetchEventSource } from '@microsoft/fetch-event-source';

@Injectable({
Expand Down Expand Up @@ -178,16 +179,21 @@ export class FastenApiService {
return this._httpClient.post<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/query`, query)
}

getResourceGraph(graphType?: string): Observable<{[resourceType: string]: ResourceFhir[]}> {
getResourceGraph(graphType?: string, page?:number): Observable<ResourceGraphResponse> {
if(!graphType){
graphType = "MedicalHistory"
}
let queryParams = {}
if(page){
//the backend is 0 indexed, but the frontend is 1 indexed
queryParams["page"] = page - 1
}

return this._httpClient.get<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/resource/graph/${graphType}`)
return this._httpClient.get<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/resource/graph/${graphType}`, {params: queryParams})
.pipe(
map((response: ResponseWrapper) => {
console.log("RESPONSE", response)
return response.data as {[name: string]: ResourceFhir[]}
return response.data as ResourceGraphResponse
})
);
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/dave/jennifer v1.6.1
github.com/dominikbraun/graph v0.15.0
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
github.com/fastenhealth/fasten-sources v0.3.1
github.com/fastenhealth/fasten-sources v0.3.2
github.com/fastenhealth/gofhir-models v0.0.5
github.com/gin-gonic/gin v1.9.0
github.com/glebarez/sqlite v1.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/fastenhealth/fasten-sources v0.3.1 h1:JtAtPWB5WErtQgPAepnISqm/fhIt7elOsFWk1a4g0yc=
github.com/fastenhealth/fasten-sources v0.3.1/go.mod h1:KUtpp65GaKlpRvl5i8zWTVZlI1yJaUPkvGVqQVEC21w=
github.com/fastenhealth/fasten-sources v0.3.2 h1:AdFayvwu88zO5JmMNhxlZDARZW1q6iBNHl9Ew8BSLHs=
github.com/fastenhealth/fasten-sources v0.3.2/go.mod h1:KUtpp65GaKlpRvl5i8zWTVZlI1yJaUPkvGVqQVEC21w=
github.com/fastenhealth/gofhir-models v0.0.5 h1:wU2Dz+/h9MzZCTRgkQzeq5l0EFuMI6C5xgCbKislFpg=
github.com/fastenhealth/gofhir-models v0.0.5/go.mod h1:xB8ikGxu3bUq2b1JYV+CZpHqBaLXpOizFR0eFBCunis=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
Expand Down

0 comments on commit 877a132

Please sign in to comment.