Skip to content

Commit

Permalink
Merge branch '9.0' into 9.1
Browse files Browse the repository at this point in the history
  • Loading branch information
himeshr committed Jul 29, 2024
2 parents 65621a0 + 499c74c commit 607f0eb
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ class AddressLevelsState {
constructor(levels = []) {
const unsortedLevels = Object.entries(_.uniqBy(levels, l => l.uuid)
.reduce((acc, {locationMappings, uuid, name, level, type, parentUuid, typeUuid, isSelected = false}) => {
acc[level] = _.defaultTo(acc[level], []).concat([{
const accumulatorKey = level + "->" + type;
// accumulating just by type affects our ability to sort the levels. accumulating just by level affects our ability to group levels of the same type
// hence using a composite key of level + type with a separator
acc[accumulatorKey] = _.defaultTo(acc[accumulatorKey], []).concat([{
uuid,
name,
level,
Expand All @@ -16,8 +19,8 @@ class AddressLevelsState {
}]);
return acc;
}, {}));
const levelTypeOrderedUnsortedLevels = _.orderBy(unsortedLevels, ([level, value]) => level, ['desc']);
this.levels = levelTypeOrderedUnsortedLevels.map(([levelNum, levels]) => {
const sortedLevels = _.orderBy(unsortedLevels, ([levelKey, value]) => levelKey, ['desc']);
this.levels = sortedLevels.map(([levelKey, levels]) => {
const levelType = levels[0].type;
const other = _.find(levels, (level) => _.startsWith(level.name, "Other"));
if(!_.isNil(other)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import _ from "lodash";
import FormMappingService from "../../service/FormMappingService";
import {ArrayUtil} from "openchs-models";
import AddressLevelState from '../common/AddressLevelsState';
import General from "../../utility/General";

class FiltersActions {

Expand Down Expand Up @@ -64,10 +65,8 @@ class FiltersActions {
addressLevelState: action.addressLevelState
};
const addressLevelService = beans.get(AddressLevelService);
const lowestSelectedAddressLevels = action.addressLevelState.lowestSelectedAddresses;
const lowestAddressLevels = lowestSelectedAddressLevels
.reduce((acc, parent) => acc.concat(addressLevelService.getDescendantsOfNode(parent)), []);
newState.locationSearchCriteria.toggleLowestAddresses(lowestAddressLevels);
const toMatchAddresses = [...action.addressLevelState.selectedAddresses].concat(addressLevelService.getAllDescendants(action.addressLevelState.selectedAddresses));
newState.locationSearchCriteria.toggleLowestAddresses(toMatchAddresses);
return newState;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {firebaseEvents, logEvent} from "../../utility/Analytics";
import RealmQueryService from "../../service/query/RealmQueryService";
import SubjectTypeService from "../../service/SubjectTypeService";
import {DashboardCacheFilter} from "openchs-models";
import General from "../../utility/General";

function getApplicableEncounterTypes(holder) {
return _.isEmpty(holder.selectedGeneralEncounterTypes) ? holder.selectedEncounterTypes : holder.selectedGeneralEncounterTypes;
Expand Down
10 changes: 9 additions & 1 deletion packages/openchs-android/src/service/AddressLevelService.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Service from '../framework/bean/Service';
import {AddressLevel} from 'avni-models';
import {AddressLevel} from 'openchs-models';
import BaseAddressLevelService from "./BaseAddressLevelService";
import _ from "lodash";

@Service("addressLevelService")
class AddressLevelService extends BaseAddressLevelService {
Expand All @@ -11,6 +12,13 @@ class AddressLevelService extends BaseAddressLevelService {
getSchema() {
return AddressLevel.schema.name;
}

getAllDescendants(addresses) {
const addressLevelService = this;
return addresses
.filter(location => location.level === _.get(_.minBy(addresses, 'level'), 'level'))
.reduce((acc, parent) => acc.concat(addressLevelService.getDescendantsOfNode(parent)), []);
}
}

export default AddressLevelService;
21 changes: 17 additions & 4 deletions packages/openchs-android/src/service/RuleEvaluationService.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,21 +464,34 @@ class RuleEvaluationService extends BaseService {
params: _.merge({visitSchedule: scheduledVisits, entity, entityContext, services: this.services}, this.getCommonParams()),
imports: getImports()
});
this.checkIfScheduledVisitsAreValid(nextVisits);
return nextVisits;
} catch (e) {
General.logDebug("Rule-Failure", `New enrolment decision failed for form: ${form.uuid}`);
General.logDebug("Rule-Failure", `Visit Schedule failed for form: ${form.uuid}`);
this.saveFailedRules(e, form.uuid, this.getIndividualUUID(entity, entityName));
}
} else {
} else if (!_.isEmpty(rulesFromTheBundle)) {
const nextVisits = rulesFromTheBundle
.reduce((schedule, rule) => {
General.logDebug(`RuleEvaluationService`, `Executing Rule: ${rule.name} Class: ${rule.fnName}`);
return this.runRuleAndSaveFailure(rule, entityName, entity, schedule, visitScheduleConfig, null, entityContext);
}, scheduledVisits);
General.logDebug("RuleEvaluationService - Next Visits", nextVisits);
return nextVisits;
try {
this.checkIfScheduledVisitsAreValid(nextVisits);
return nextVisits;
} catch(e) {
General.logDebug("Rule-Failure", `Visit Schedule (old) failed for form: ${form.uuid}`);
this.saveFailedRules(e, form.uuid, this.getIndividualUUID(entity, entityName));
}
}
return defaultVisitSchedule;
}

checkIfScheduledVisitsAreValid(nextVisits) {
if (_.some(nextVisits, visit => _.isNil(visit.earliestDate))) {
throw new Error("Visit(s) scheduled without earliestDate");
}
return scheduledVisits;
}

getChecklists(entity, entityName, defaultChecklists = []) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,6 @@ class IndividualSearchCriteria {
this.allowedSubjectUUIDs = subjectUUIDs;
}

toggleLowestAddress(lowestAddress) {
if (BaseEntity.collectionHasEntity(this.lowestAddressLevels, lowestAddress))
BaseEntity.removeFromCollection(this.lowestAddressLevels, lowestAddress);
else
this.lowestAddressLevels.push(lowestAddress);
}

toggleLowestAddresses(lowestAddresses) {
this.lowestAddressLevels = lowestAddresses;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ class DashboardFilterService extends BaseService {
} else {
const addressLevelService = this.getService(AddressLevelService);
const addressFilterValues = [...filterValue.selectedAddresses];
const descendants = filterValue.selectedAddresses
.filter(location => location.level === _.get(_.minBy(filterValue.selectedAddresses, 'level'), 'level'))
.reduce((acc, parent) => acc.concat(addressLevelService.getDescendantsOfNode(parent)), []);

const descendants = addressLevelService.getAllDescendants(filterValue.selectedAddresses);
ruleInput.filterValue = addressFilterValues.concat(descendants
.map(addressLevel => _.pick(addressLevel, ['uuid', 'name', 'level', 'type', 'parentUuid'])));
General.logDebug('DashboardFilterService', `Effective address filters: ${JSON.stringify(_.countBy(ruleInput.filterValue, "type"))}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/openchs-android/src/utility/General.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class General {
}

static toISTDate(x) {
if (x.toString().includes("18:30:00"))
if (x && x.toString().includes("18:30:00"))
return moment(x).add(330, "m").toDate();
return x;
}
Expand Down
24 changes: 12 additions & 12 deletions packages/openchs-android/src/views/customDashboard/CardListView.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import React from 'react';
import Styles from '../primitives/Styles';
import {CountResult} from './CountResult';
import _, {get} from 'lodash';
import MCIcon from 'react-native-vector-icons/MaterialCommunityIcons';
import Colors from '../primitives/Colors';

export const CardListView = ({reportCard, I18n, onCardPress, countResult, index, isLastCard}) => {
const {name, colour, itemKey} = reportCard;
const cardName = (countResult && countResult.cardName) || name;
const textColor = (countResult && countResult.textColor) || Styles.blackColor;
const descriptionColor = (countResult && countResult.textColor) || Styles.blackColor;
const cardColor = (countResult && countResult.cardColor) || colour || '#999999';
const chevronColor = Colors.darker(0.1, cardColor);
const clickable = get(countResult, 'clickable');

const renderNumber = () => {
Expand All @@ -22,6 +23,9 @@ export const CardListView = ({reportCard, I18n, onCardPress, countResult, index,
secondary={countResult.secondaryValue}
primaryStyle={[styles.primaryTextStyle, {color: textColor}, countResult.hasErrorMsg && styles.cardPrimaryTextErrorStyle]}
secondaryStyle={[styles.secondaryTextStyle, {color: textColor}, countResult.hasErrorMsg && styles.cardSecondaryTextErrorStyle]}
clickable={clickable}
chevronColor={chevronColor}
colour={textColor}
/>
);
};
Expand All @@ -34,10 +38,6 @@ export const CardListView = ({reportCard, I18n, onCardPress, countResult, index,
]}>
<View style={styles.nameContainer}>
<Text style={[styles.nameTextStyle, {color: descriptionColor}]}>{I18n.t(cardName)}</Text>
<View style={{borderRadius: 6, alignSelf: 'flex-end'}}>
{clickable &&
<MCIcon name={'chevron-right'} size={40} color={colour} style={{opacity: 0.8}}/>}
</View>
</View>
<View style={[styles.numberContainer]}>
{renderNumber()}
Expand All @@ -51,7 +51,7 @@ const styles = StyleSheet.create({
rowContainer: {
flexDirection: 'row',
flexWrap: 'nowrap',
height: 100,
minHeight: 100,
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#DCDCDC'
},
Expand All @@ -70,17 +70,16 @@ const styles = StyleSheet.create({
},
nameContainer: {
marginLeft: 5,
paddingHorizontal: 3,
paddingHorizontal: 16,
flex: 0.7,
flexDirection: 'row',
paddingLeft: 16,
alignItems: 'center',
borderRightWidth: StyleSheet.hairlineWidth,
borderColor: '#DCDCDC'
},
nameTextStyle: {
paddingTop: 15,
fontSize: Styles.titleSize,
width: '90%'
paddingVertical: 15,
fontSize: Styles.normalTextSize
},
numberContainer: {
flex: 0.3,
Expand All @@ -92,7 +91,8 @@ const styles = StyleSheet.create({
fontStyle: 'normal',
},
secondaryTextStyle: {
fontSize: 16,
fontSize: 14,
fontWeight: '300',
fontStyle: 'normal',
},
cardPrimaryTextErrorStyle: {
Expand Down
18 changes: 10 additions & 8 deletions packages/openchs-android/src/views/customDashboard/CardTileView.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const renderNumber = function (countResult = {}, textColor) {
);
};

const cardGap = 16;
const cardGap = 14;

export const CardTileView = ({index, reportCard, I18n, onCardPress, countResult}) => {
const {name, colour, itemKey, iconName} = reportCard;
Expand All @@ -56,8 +56,10 @@ export const CardTileView = ({index, reportCard, I18n, onCardPress, countResult}
marginTop: cardGap,
marginLeft: index % 2 !== 0 ? cardGap : 0,
width: cardWidth,
minHeight: 100,
backgroundColor: cardColor,
borderColor: cardBorderColor,
borderWidth: 1,
paddingLeft: 16,
}]}>
<View style={styles.cardNameContainerStyle}>
Expand All @@ -69,14 +71,14 @@ export const CardTileView = ({index, reportCard, I18n, onCardPress, countResult}
{iconName && renderIcon(iconName, textColor)}
</View>
</View>
<View style={{position: 'absolute', right: 0, bottom: 0, height: 40, width: 40}}>
<View style={{position: 'absolute', right: 0, bottom: 0, height: 20, width: 20}}>
<View style={{
backgroundColor: chevronColor,
borderTopLeftRadius: 10, borderBottomRightRadius: 10,
height: 40, width: 40, alignItems: 'center', justifyContent: 'center'
borderTopLeftRadius: 4, borderBottomRightRadius: 4,
height: 20, width: 20, alignItems: 'center', justifyContent: 'center'
}}>
{clickable &&
<MCIcon name={'chevron-right'} size={30} color={textColor} style={{opacity: 0.8}}/>}
<MCIcon name={'chevron-right'} size={20} color={textColor} style={{opacity: 0.8}}/>}
</View>
</View>
</View>
Expand All @@ -90,11 +92,11 @@ const styles = StyleSheet.create({
borderWidth: StyleSheet.hairlineWidth,
},
cardNameTextStyle: {
fontSize: 18,
fontSize: Styles.normalTextSize,
fontStyle: 'normal'
},
cardNameContainerStyle: {
paddingBottom: 40,
paddingBottom: 20,
marginRight: 12
},
cardPrimaryTextStyle: {
Expand All @@ -103,7 +105,7 @@ const styles = StyleSheet.create({
fontStyle: 'normal',
},
cardSecondaryTextStyle: {
fontSize: 16,
fontSize: 14,
fontStyle: 'normal',
},
iconContainer: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import React from 'react';
import {Text, View} from "react-native";
import MCIcon from 'react-native-vector-icons/MaterialCommunityIcons';

export const CountResult = ({primary, secondary, primaryStyle, secondaryStyle, direction}) => {
export const CountResult = ({primary, secondary, primaryStyle, secondaryStyle, direction, clickable, chevronColor, colour}) => {
return (
<View style={{flex: 1, flexDirection: direction, alignItems: 'center', justifyContent: 'center'}}>
<Text style={primaryStyle}>{primary}</Text>
{secondary ?
<Text style={[secondaryStyle, direction === 'row' ? {marginLeft: 8} : {}]}>
{secondary}
({secondary})
</Text> :
null}

<View style={{position: 'absolute', right: 0, bottom: 0, height: 20, width: 20, backgroundColor: chevronColor,
borderTopLeftRadius: 4, borderBottomRightRadius: 4,}}>
{clickable &&
<MCIcon name={'chevron-right'} size={20} color={colour} style={{opacity: 0.8}}/>}
</View>
</View>
)
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import General from "../../src/utility/General";
import _ from 'lodash';

class TestAddressLevelFactory {
static createWithDefaults({parent, level, name}) {
static createWithDefaults({parent, level, name, type}) {
const addressLevel = new AddressLevel();
addressLevel.uuid = General.randomUUID();
addressLevel.name = _.defaultTo(name, addressLevel.uuid);
addressLevel.type = level+'_level';
addressLevel.type = type || level+'_level';
addressLevel.level = level;
if (!_.isNil(parent)) {
const locationMapping = new LocationMapping();
Expand Down
18 changes: 18 additions & 0 deletions packages/openchs-android/test/state/AddressLevelStateTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,22 @@ it('should sort addressLevels by levelType and within each levelType by name', f
assert.equal(levels[0].locationMappings[0].parent.uuid, parentLevelElement[0].uuid);
}
});
});

it ('should treat multiple address level types at the same level as separate', function() {
const addrLevel1 = TestAddressLevelFactory.createWithDefaults({level: 1, type: 'a', name: 'location1'});
const addrLevel2 = TestAddressLevelFactory.createWithDefaults({level: 1, type: 'b', name: 'location2'});
const addrLevel3 = TestAddressLevelFactory.createWithDefaults({level: 1, type: 'c', name: 'location3'});

const allLevels = [
addrLevel1, addrLevel2, addrLevel3,
]
// Shuffle the addressLevels
let addressLevelsState = new AddressLevelsState(_.shuffle(allLevels));
assert.equal(addressLevelsState.levels.length, 3);
addressLevelsState.levels.map(([levelType, levels]) => {
assert.equal(levels.length, 1); // 1 group for each levelType
assert.equal(levels[0].type, levelType); // group consists of same type of addressLevels
});

});

0 comments on commit 607f0eb

Please sign in to comment.