Skip to content

Commit

Permalink
in response wrapper, the error field is optional
Browse files Browse the repository at this point in the history
Dashboard widget query processing is now done in the dashboard-widget.
added tests for dashboard-widget.
  • Loading branch information
AnalogJ committed Jul 27, 2023
1 parent 779948a commit 07f0a1f
Show file tree
Hide file tree
Showing 11 changed files with 593 additions and 205 deletions.
2 changes: 1 addition & 1 deletion frontend/src/app/models/response-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export class ResponseWrapper {
data: any
success: boolean
error: string
error?: string
}
74 changes: 0 additions & 74 deletions frontend/src/app/services/fasten-api.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,78 +26,4 @@ describe('FastenApiService', () => {
expect(service).toBeTruthy();
});

it('fhirPathMapQueryFn should generate a valid select map with aliases', () => {
//setup
let patient = {
"resourceType": "Patient",
"id": "example",
"address": [
{
"use": "home",
"city": "PleasantVille",
"type": "both",
"state": "Vic",
"line": [
"534 Erewhon St"
],
"postalCode": "3999",
"period": {
"start": "1974-12-25"
},
"district": "Rainbow",
"text": "534 Erewhon St PeasantVille, Rainbow, Vic 3999"
}
]
}

let query = {
// use: string
select: ['address.use', "address.where(type='both').state as state"],
from: 'Patient',
where: {'id':'example'}

} as DashboardWidgetQuery


let query2 = {
// use: string
select: ['*', "address.where(type='both').use | address.city as joined"],
from: 'Patient',
where: {'id':'example'}

} as DashboardWidgetQuery


//test
let fn = service.fhirPathMapQueryFn(query)
expect(fn(patient)).toEqual({ "address.use": [ 'home' ], "state": [ 'Vic' ], 'id': 'example', 'resourceType': 'Patient' })

// let fn2 = service.fhirPathMapQueryFn(query2)
let fn2 = service.fhirPathMapQueryFn(query2)
expect(fn2(patient)).toEqual({
"joined": [ 'home', 'PleasantVille' ],
"*": {
"resourceType": "Patient",
"id": "example",
"address": [
{
"use": "home",
"city": "PleasantVille",
"type": "both",
"state": "Vic",
"line": [
"534 Erewhon St"
],
"postalCode": "3999",
"period": {
"start": "1974-12-25"
},
"district": "Rainbow",
"text": "534 Erewhon St PeasantVille, Rainbow, Vic 3999"
}
]
}, 'id': 'example', 'resourceType': 'Patient' })


});
});
91 changes: 2 additions & 89 deletions frontend/src/app/services/fasten-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,46 +162,11 @@ export class FastenApiService {

//TODO: add caching here, we dont want the same query to be run multiple times whne loading the dashboard.
// we should also add a way to invalidate the cache when a source is synced
queryResources(query?: DashboardWidgetQuery): Observable<any[]> {
//this function is special, as it returns the raw response, for processing in the DashboardWidgetComponent
queryResources(query?: DashboardWidgetQuery): Observable<ResponseWrapper> {


return this._httpClient.post<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/query`, query)
.pipe(
map((response: ResponseWrapper) => {
console.log("RESPONSE", response)

//TODO: eventually do filtering in backend, however until sql-on-fhir project is completed, we'll be doing it here
//it's less preformant, but it's a temporary solution
if(!response.data || !response.data.length){
console.log("NO QUERY DATA FOUND")
return []
}
let results = response.data
.map((resource: ResourceFhir) => {
if (!resource.resource_raw) {
return null
}
return this.fhirPathMapQueryFn(query)(resource.resource_raw)
})

if(query.aggregation_type){
switch (query.aggregation_type) {
case "countBy":

return Object.entries(_[query.aggregation_type](results, ...(query.aggregation_params || []))).map(pair => {
return {key: pair[0], value: pair[1]}
})

break;
default:
throw new Error("unsupported aggregation type")
}
}
else {
return results
}
})
);
}

getResourceGraph(graphType?: string): Observable<{[resourceType: string]: ResourceFhir[]}> {
Expand Down Expand Up @@ -272,56 +237,4 @@ export class FastenApiService {
return of(new BinaryModel(attachmentModel));
}
}

//private methods

// This function will convert DashboardWidgetQuery.select filters into a FHIRPath query strings and return the results
// as a map (keyed by the select alias)
// ie. `name.where(given='Jim')` will be converted to `Patient.name.where(given='Jim')`
// ie. `name.where(given='Jim') as GivenName` will be converted to `Patient.name.where(given='Jim')` and be stored in the returned map as GivenName`
// the returned map will always contain a `id` key, which will be the resource id and a `resourceType` key, which will be the resource type

fhirPathMapQueryFn(query: DashboardWidgetQuery): (rawResource: any) => { [name:string]: string | string[] | any } {
let selectPathFilters: { [name:string]: string } = query.select.reduce((selectAliasMap, selectPathFilter): { [name:string]: string } => {
let alias = selectPathFilter
let selectPath = selectPathFilter
if(selectPathFilter.indexOf(" as ") > -1){
let selectPathFilterParts = selectPathFilter.split(" as ")
selectPath = selectPathFilterParts[0] as string
alias = selectPathFilterParts[1] as string
} else if(selectPathFilter.indexOf(" AS ") > -1){
let selectPathFilterParts = selectPathFilter.split(" AS ")
selectPath = selectPathFilterParts[0] as string
alias = selectPathFilterParts[1] as string
}

selectAliasMap[alias] = selectPath
// if(selectPath == '*'){
// selectAliasMap[alias] = selectPath
// } else {
// selectAliasMap[alias] = `${query.from}.${selectPath}`
// }

return selectAliasMap
}, {})

// console.log(selectPathFilters)
return function(rawResource: any):{ [name:string]: string | string[] | any } {
let results = {}
for(let alias in selectPathFilters){
let selectPathFilter = selectPathFilters[alias]
if(selectPathFilter == '*'){
results[alias] = rawResource
} else {
results[alias] = fhirpath.evaluate(rawResource, selectPathFilter)
}
}

results["id"] = rawResource.id
results["resourceType"] = rawResource.resourceType
return results
}
}


}
Loading

0 comments on commit 07f0a1f

Please sign in to comment.