Skip to content

Commit

Permalink
#836 - inMemory filtering after removing subquery for observations. a…
Browse files Browse the repository at this point in the history
…bility to set server in dev settings
  • Loading branch information
petmongrels committed Feb 3, 2023
1 parent 3129731 commit 05c7de2
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 51 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ rm_db:
kill_realm_browser:
pkill "Realm Browser" || true

open_db: rm_db get_db ## Open realmdb in Realm Browser
open_db: rm_db get_db open_db_only
open_db_only:
$(call _open_resource,../db/default.realm)
# </db>

Expand Down
8 changes: 8 additions & 0 deletions makefiles/util.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@ open-ci-page:

open-checkout-hook:
vi .git/hooks/post-checkout

s3-dump-page:
ifndef org
@echo "Please provide org prefix in org param"
exit 1
else
open "https://s3.console.aws.amazon.com/s3/buckets/prod-user-media?region=ap-south-1&prefix=$(org)/&showversions=false"
endif
38 changes: 9 additions & 29 deletions packages/openchs-android/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/openchs-android/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"lodash": "4.17.21",
"moment": "2.29.4",
"native-base": "3.4.9",
"openchs-models": "1.27.18",
"openchs-models": "1.27.19",
"prop-types": "15.8.1",
"react": "18.2.0",
"react-native": "0.69.7",
Expand Down
1 change: 1 addition & 0 deletions packages/openchs-android/src/Playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function executeQuery(queryString, type) {
objects = objects.filtered(queryString);
return objects.map(_.identity).length;
} catch (e) {
console.error(e);
return -1;
}
}
Expand Down
29 changes: 17 additions & 12 deletions packages/openchs-android/src/service/CustomFilterService.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
Concept,
CustomFilter,
GroupSubject,
} from "avni-models";
ObservationsHolder
} from "openchs-models";
import General from "../utility/General";
import _ from "lodash";
import ConceptService from "./ConceptService";
Expand Down Expand Up @@ -118,7 +119,7 @@ class CustomFilterService extends BaseService {

// Note that the query is run for every filter(concept) separately, this is because we don't have
// joins in realm and after getting latest from each filter(concept) we need to query for selected concept answer.
queryFromLatestObservation(schemaName, conceptFilters, selectedAnswerFilters, scopeFilters, sortFilter, indFunc, widget) {
queryFromLatestObservation(schemaName, conceptFilters, selectedAnswerFilters, scopeFilters, sortFilter, indFunc, widget, inMemoryFilter) {
const latestEncounters = this.db.objects(schemaName)
.filtered(`voided = false `)
//limit the scope of query by giving encounter/program uuid
Expand All @@ -129,15 +130,16 @@ class CustomFilterService extends BaseService {
.filtered(_.isEmpty(sortFilter) ? 'uuid != null' : ` ${sortFilter} `);

return widget === CustomFilter.widget.Range ? this.filterForRangeWidgetType(latestEncounters, selectedAnswerFilters, indFunc)
: this.filterForFixedWidgetType(latestEncounters, schemaName, selectedAnswerFilters, indFunc);
: this.filterForFixedWidgetType(latestEncounters, schemaName, selectedAnswerFilters, indFunc, inMemoryFilter);
}

filterForFixedWidgetType(latestEncounters, schemaName, selectedAnswerFilters, indFunc) {
filterForFixedWidgetType(latestEncounters, schemaName, selectedAnswerFilters, indFunc, inMemoryFilter) {
//cannot append next filtered to this query because sorting happens at the end of query and we will not get expected result.
//so we get the most recent encounters from above query and pass it down to the next query.
return _.isEmpty(latestEncounters) ? [] : [...latestEncounters
//check if selected filter is present in the observations
.filtered(` ${selectedAnswerFilters()} `)
.filterInternal((obsHolder) => inMemoryFilter(obsHolder))
.map(indFunc)
];
}
Expand Down Expand Up @@ -190,8 +192,8 @@ class CustomFilterService extends BaseService {
const selectedOption = _.head(selectedOptions);
switch (concept.datatype) {
case (Concept.dataType.Coded) :
const codedFilterQuery = _.map(selectedOptions, c => ` (concept.uuid == '${concept.uuid}' AND valueJSON CONTAINS[c] '${c.uuid}') `).join(" OR ");
return () => this.getObsSubQueryForQuery(codedFilterQuery);
const codedFilterQuery = _.map(selectedOptions, c => ` (observations.concept.uuid == '${concept.uuid}' AND observations.valueJSON CONTAINS[c] '${c.uuid}') `).join(" OR ");
return () => codedFilterQuery;
case (Concept.dataType.Text) :
case (Concept.dataType.Notes) :
case (Concept.dataType.Id) :
Expand Down Expand Up @@ -239,15 +241,15 @@ class CustomFilterService extends BaseService {
return filter.join(" AND ");
}

queryConceptTypeFilters(scope, scopeParameters, selectedAnswerFilters, conceptFilter, widget) {
queryConceptTypeFilters(scope, scopeParameters, selectedAnswerFilters, conceptFilter, widget, inMemoryFilter) {
switch (scope) {
case CustomFilter.scope.ProgramEncounter : {
const encounterOptions = _.map(scopeParameters.encounterTypeUUIDs, e => `encounterType.uuid == "${e}"`).join(" OR ");
const programOptions = _.map(scopeParameters.programUUIDs, p => `programEnrolment.program.uuid == "${p}"`).join(" OR ");
const scopeFilters = this.createProgramEncounterScopeFilter(encounterOptions, programOptions);
const scopeFiltersWithNonExit = `(${scopeFilters}) and programEnrolment.programExitDateTime = null`;
const sortFilter = 'TRUEPREDICATE sort(programEnrolment.individual.uuid asc , encounterDateTime desc) Distinct(programEnrolment.individual.uuid)';
const individualUUIDs = this.queryFromLatestObservation(ProgramEncounter.schema.name, conceptFilter, selectedAnswerFilters, scopeFiltersWithNonExit, sortFilter, enc => enc.programEnrolment.individual.uuid, widget);
const individualUUIDs = this.queryFromLatestObservation(ProgramEncounter.schema.name, conceptFilter, selectedAnswerFilters, scopeFiltersWithNonExit, sortFilter, enc => enc.programEnrolment.individual.uuid, widget, inMemoryFilter);
this.updateIndividuals(individualUUIDs);
break;
}
Expand All @@ -256,20 +258,20 @@ class CustomFilterService extends BaseService {
const scopeFilters = this.createProgramEncounterScopeFilter(null, programOptions);
const scopeFiltersWithNonExit = `(${scopeFilters}) and programExitDateTime = null`;
const sortFilter = 'TRUEPREDICATE sort(individual.uuid asc , enrolmentDateTime desc) Distinct(individual.uuid)';
const individualUUIDs = this.queryFromLatestObservation(ProgramEnrolment.schema.name, conceptFilter, selectedAnswerFilters, scopeFiltersWithNonExit, sortFilter, enl => enl.individual.uuid, widget);
const individualUUIDs = this.queryFromLatestObservation(ProgramEnrolment.schema.name, conceptFilter, selectedAnswerFilters, scopeFiltersWithNonExit, sortFilter, enl => enl.individual.uuid, widget, inMemoryFilter);
this.updateIndividuals(individualUUIDs);
break;
}
case CustomFilter.scope.Registration : {
const individualUUIDs = this.queryFromLatestObservation(Individual.schema.name, null, selectedAnswerFilters, null, null, ind => ind.uuid, widget);
const individualUUIDs = this.queryFromLatestObservation(Individual.schema.name, null, selectedAnswerFilters, null, null, ind => ind.uuid, widget, inMemoryFilter);
this.updateIndividuals(individualUUIDs);
break;
}
case CustomFilter.scope.Encounter : {
const encounterOptions = _.map(scopeParameters.encounterTypeUUIDs, e => `encounterType.uuid == "${e}"`).join(" OR ");
const scopeFilters = this.createProgramEncounterScopeFilter(encounterOptions, null);
const sortFilter = 'TRUEPREDICATE sort(individual.uuid asc , encounterDateTime desc) Distinct(individual.uuid)';
const individualUUIDs = this.queryFromLatestObservation(Encounter.schema.name, conceptFilter, selectedAnswerFilters, scopeFilters, sortFilter, enc => enc.individual.uuid, widget);
const individualUUIDs = this.queryFromLatestObservation(Encounter.schema.name, conceptFilter, selectedAnswerFilters, scopeFilters, sortFilter, enc => enc.individual.uuid, widget, inMemoryFilter);
this.updateIndividuals(individualUUIDs);
break;
}
Expand All @@ -292,7 +294,10 @@ class CustomFilterService extends BaseService {
const conceptFilter = `observations.concept.uuid == "${conceptUUID}"`;
switch (type) {
case CustomFilter.type.Concept :
this.queryConceptTypeFilters(scope, scopeParameters, selectedAnswerFilterQuery, conceptFilter, widget);
const concept = this.getService(ConceptService).findByUUID(conceptUUID);
const inMemoryFilter = concept.isCodedConcept() ?
(obsHolder) => ObservationsHolder.hasAnyAnswer(obsHolder, conceptUUID, selectedOptions.map(x => x.uuid),) : null;
this.queryConceptTypeFilters(scope, scopeParameters, selectedAnswerFilterQuery, conceptFilter, widget, inMemoryFilter);
break;
case CustomFilter.type.RegistrationDate:
this.updateIndividuals(this.queryEntity(Individual.schema.name, selectedAnswerFilterQuery, null, ind => ind.uuid));
Expand Down
21 changes: 13 additions & 8 deletions packages/openchs-android/src/views/settings/DevSettingsView.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {Text, TouchableNativeFeedback, View} from "react-native";
import {Text, TouchableNativeFeedback, View, TextInput, ScrollView} from "react-native";
import React from "react";
import AbstractComponent from "../../framework/view/AbstractComponent";
import Path from "../../framework/routing/Path";
import _ from "lodash";
import General from "../../utility/General";
import {SettingsActionsNames as Actions} from "../../action/SettingsActions";
import {SettingsActionsNames, SettingsActionsNames as Actions} from "../../action/SettingsActions";
import RadioGroup, {RadioLabelValue} from "../primitives/RadioGroup";
import Reducers from "../../reducer";
import AppHeader from "../common/AppHeader";
Expand All @@ -15,7 +15,7 @@ import Styles from "../primitives/Styles";
import Fonts from "../primitives/Fonts";
import Colors from "../primitives/Colors";
import RuleEvaluationService from "../../service/RuleEvaluationService";
import {Rule} from 'avni-models';
import {Rule} from 'openchs-models';

@Path('/devSettingsView')
class DevSettingsView extends AbstractComponent {
Expand Down Expand Up @@ -58,26 +58,31 @@ class DevSettingsView extends AbstractComponent {

renderDevOptions() {
if (__DEV__) {
const {rulesToRun, settings} = this.state;
const labelValues = Object.entries(this.entityMap)
.map(([displayName, value]) => new RadioLabelValue(displayName, value));
return (<View>
<RadioGroup
onPress={({value}) => this.dispatchAction(Actions.ON_RULE_CHANGE, {value: value})}
labelValuePairs={labelValues}
labelKey='Rules to run'
selectionFn={(ruleToRun) => this.state.rulesToRun.indexOf(ruleToRun) > -1}
selectionFn={(ruleToRun) => rulesToRun.indexOf(ruleToRun) > -1}
validationError={null}
multiSelect={true}
style={{marginTop: Distances.VerticalSpacingBetweenFormElements}}
/>
<TouchableNativeFeedback onPress={() => this.runRules(this.state.rulesToRun)}>
<TouchableNativeFeedback onPress={() => this.runRules(rulesToRun)}>
<View style={Styles.basicPrimaryButtonView}>
<Text style={{
fontSize: Fonts.Medium,
color: Colors.TextOnPrimaryColor
}}>Run {this.state.rulesToRun.length === 0 ? 'All' : 'Selected'} Rules</Text>
}}>Run {rulesToRun.length === 0 ? 'All' : 'Selected'} Rules</Text>
</View>
</TouchableNativeFeedback>
<View style={{marginTop: 20}}>
<Text>Server URL:</Text>
<TextInput value={settings.serverURL} onChangeText={(text) => this.dispatchAction(Actions.ON_SERVER_URL_CHANGE, {value: text})}/>
</View>
</View>);
}
}
Expand All @@ -87,10 +92,10 @@ class DevSettingsView extends AbstractComponent {
<CHSContainer>
<CHSContent>
<AppHeader title={'Dev Settings'}/>
<View style={{paddingHorizontal: Distances.ContentDistanceFromEdge}}>
<ScrollView style={{paddingHorizontal: Distances.ContentDistanceFromEdge}}>
{this.renderDevOptions()}
{this.renderLogLevels()}
</View>
</ScrollView>
</CHSContent>
</CHSContainer>
);
Expand Down

0 comments on commit 05c7de2

Please sign in to comment.