diff --git a/packages/openchs-android/package-lock.json b/packages/openchs-android/package-lock.json index 8cf9e0d65..459c01f64 100644 --- a/packages/openchs-android/package-lock.json +++ b/packages/openchs-android/package-lock.json @@ -29,7 +29,7 @@ "lodash": "4.17.21", "moment": "2.29.4", "native-base": "3.4.9", - "openchs-models": "1.27.14", + "openchs-models": "1.27.17", "prop-types": "15.8.1", "react": "18.2.0", "react-native": "0.69.7", @@ -5870,9 +5870,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.189", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", - "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==" + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" }, "node_modules/@types/lodash.has": { "version": "4.5.7", @@ -6478,6 +6478,11 @@ "node": ">=4" } }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, "node_modules/async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -7920,11 +7925,6 @@ "git-clang-format": "bin/git-clang-format" } }, - "node_modules/clang-format/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, "node_modules/class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -10194,12 +10194,6 @@ "node": ">=10" } }, - "node_modules/grunt-legacy-util/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, "node_modules/grunt-legacy-util/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -17065,11 +17059,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/metro/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, "node_modules/metro/node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -18654,9 +18643,9 @@ } }, "node_modules/openchs-models": { - "version": "1.27.14", - "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.27.14.tgz", - "integrity": "sha512-Uchiu3MNfrvIoW8VbvvZMtrBU2O+jcIoG6w2su0oHECi+u8aPC7pgvJSwAwzS9RBy8LUoDANMHSujcQIWyASEg==", + "version": "1.27.17", + "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.27.17.tgz", + "integrity": "sha512-oAhrPVy+UMOHlSZv7eNwK6LtVyTsjjml4Jcbsid+IZVBCrCJK8lUbPlJxfVpphkeXuYZa6npNXk+vYXiP/ZmpA==", "peerDependencies": { "lodash": "*", "moment": "*" @@ -21063,9 +21052,9 @@ } }, "node_modules/realm-network-transport/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", + "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -29068,9 +29057,9 @@ } }, "@types/lodash": { - "version": "4.14.189", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", - "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==" + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" }, "@types/lodash.has": { "version": "4.5.7", @@ -29596,6 +29585,11 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -30758,13 +30752,6 @@ "async": "^3.2.3", "glob": "^7.0.0", "resolve": "^1.1.6" - }, - "dependencies": { - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - } } }, "class-utils": { @@ -32656,12 +32643,6 @@ "which": "~2.0.2" }, "dependencies": { - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -37194,11 +37175,6 @@ "color-convert": "^2.0.1" } }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -39057,9 +39033,9 @@ } }, "openchs-models": { - "version": "1.27.14", - "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.27.14.tgz", - "integrity": "sha512-Uchiu3MNfrvIoW8VbvvZMtrBU2O+jcIoG6w2su0oHECi+u8aPC7pgvJSwAwzS9RBy8LUoDANMHSujcQIWyASEg==" + "version": "1.27.17", + "resolved": "https://registry.npmjs.org/openchs-models/-/openchs-models-1.27.17.tgz", + "integrity": "sha512-oAhrPVy+UMOHlSZv7eNwK6LtVyTsjjml4Jcbsid+IZVBCrCJK8lUbPlJxfVpphkeXuYZa6npNXk+vYXiP/ZmpA==" }, "opencollective-postinstall": { "version": "2.0.3", @@ -40960,9 +40936,9 @@ }, "dependencies": { "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", + "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", "requires": { "whatwg-url": "^5.0.0" } diff --git a/packages/openchs-android/src/action/mydashboard/MyDashboardActions.js b/packages/openchs-android/src/action/mydashboard/MyDashboardActions.js index d8b83ad42..9cdaa3b3a 100644 --- a/packages/openchs-android/src/action/mydashboard/MyDashboardActions.js +++ b/packages/openchs-android/src/action/mydashboard/MyDashboardActions.js @@ -244,7 +244,7 @@ class MyDashboardActions { const genderQuery = (path) => _.map(action.selectedGenders, (gender) => `${path} = "${gender.name}"`); const customFilterService = context.get(CustomFilterService); - var individualUUIDs = []; + let individualUUIDs = []; const selectedCustomFilterBySubjectType = _.mapValues(action.selectedCustomFilters, selectedFilters => { const s = selectedFilters.filter(filter => filter.subjectTypeUUID === action.selectedSubjectType.uuid); return s.length === 0 ? [] : s diff --git a/packages/openchs-android/src/service/IndividualService.js b/packages/openchs-android/src/service/IndividualService.js index e5fac2877..dd63a8b83 100644 --- a/packages/openchs-android/src/service/IndividualService.js +++ b/packages/openchs-android/src/service/IndividualService.js @@ -422,17 +422,17 @@ class IndividualService extends BaseService { fromDate) .filtered((_.isEmpty(addressQuery) ? 'uuid != null' : `${addressQuery}`)) .map((individual) => { - const registrationDate = individual.registrationDate; - return { - individual, - visitInfo: { - uuid: individual.uuid, - visitName: [], - groupingBy: General.formatDate(registrationDate), - sortingBy: registrationDate, - allow: true, - } - }; + const registrationDate = individual.registrationDate; + return { + individual, + visitInfo: { + uuid: individual.uuid, + visitName: [], + groupingBy: General.formatDate(registrationDate), + sortingBy: registrationDate, + allow: true, + } + }; }) .reduce(this._uniqIndividualWithVisitName, new Map()) .values()] diff --git a/packages/openchs-android/src/views/common/ProgramFilter.js b/packages/openchs-android/src/views/common/ProgramFilter.js index 300f90d7d..897f6048a 100644 --- a/packages/openchs-android/src/views/common/ProgramFilter.js +++ b/packages/openchs-android/src/views/common/ProgramFilter.js @@ -28,17 +28,17 @@ class ProgramFilter extends AbstractComponent { const valueLabelPairs = this.props.visits.map(({uuid, operationalProgramName, operationalEncounterTypeName, name}) => new RadioLabelValue(operationalProgramName || operationalEncounterTypeName || name, uuid, false)); return ( this.props.onToggle(label, value)} - selectionFn={(value) => this.props.selectionFn(value)} - labelKey={this.props.name} - mandatory={false} + multiSelect={this.props.multiSelect} + style={{ + marginTop: Styles.VerticalSpacingBetweenInGroupFormElements, + marginBottom: Styles.VerticalSpacingBetweenInGroupFormElements + }} + borderStyle={{borderWidth: 0}} + inPairs={true} + onPress={({label, value}) => this.props.onToggle(label, value)} + selectionFn={(value) => this.props.selectionFn(value)} + labelKey={this.props.name} + mandatory={false} labelValuePairs={valueLabelPairs}/> ); } diff --git a/packages/openchs-android/src/views/filter/FiltersView.js b/packages/openchs-android/src/views/filter/FiltersView.js index 3dfb7e2d0..aead87946 100644 --- a/packages/openchs-android/src/views/filter/FiltersView.js +++ b/packages/openchs-android/src/views/filter/FiltersView.js @@ -1,5 +1,5 @@ import React from "react"; -import {Dimensions, StyleSheet, Text, TouchableOpacity, View} from 'react-native'; +import {Dimensions, StyleSheet, FlatList, Text, TouchableOpacity, View} from 'react-native'; import AbstractComponent from "../../framework/view/AbstractComponent"; import Distances from '../primitives/Distances' import SingleSelectFilter from './SingleSelectFilter'; diff --git a/packages/openchs-android/src/views/form/ValidationErrorMessage.js b/packages/openchs-android/src/views/form/ValidationErrorMessage.js index 3e056a1d3..8af0afca3 100644 --- a/packages/openchs-android/src/views/form/ValidationErrorMessage.js +++ b/packages/openchs-android/src/views/form/ValidationErrorMessage.js @@ -15,6 +15,10 @@ class ValidationErrorMessage extends AbstractComponent { super(props, context); } + shouldComponentUpdate(nextProps, nextState, nextContext) { + return this.props.validationResult !== nextProps.validationResult; + } + render() { return _.isNil(this.props.validationResult) || this.props.validationResult.success ? : {this.I18n.t(this.props.validationResult.messageKey, this.props.validationResult.extra)}; } diff --git a/packages/openchs-android/src/views/individual/IndividualSearchResultsView.js b/packages/openchs-android/src/views/individual/IndividualSearchResultsView.js index 256aad12e..de967b92f 100644 --- a/packages/openchs-android/src/views/individual/IndividualSearchResultsView.js +++ b/packages/openchs-android/src/views/individual/IndividualSearchResultsView.js @@ -1,22 +1,44 @@ import AbstractComponent from "../../framework/view/AbstractComponent"; -import {Text, TouchableNativeFeedback, View} from "react-native"; -import ListView from "deprecated-react-native-listview"; +import {FlatList, TouchableNativeFeedback, View} from "react-native"; import PropTypes from 'prop-types'; -import React from "react"; +import React, {Component} from "react"; import Path from "../../framework/routing/Path"; -import GlobalStyles from "../primitives/GlobalStyles"; import AppHeader from "../common/AppHeader"; import Colors from "../primitives/Colors"; import General from "../../utility/General"; -import CHSContainer from "../common/CHSContainer"; -import Styles from "../primitives/Styles"; import SearchResultsHeader from "./SearchResultsHeader"; import IndividualDetailsCard from "../common/IndividualDetailsCard"; import {IndividualSearchActionNames as Actions} from "../../action/individual/IndividualSearchActions"; -import {Individual} from "openchs-models"; -import ListViewHelper from "../../utility/ListViewHelper"; +import {getUnderlyingRealmCollection, Individual} from "openchs-models"; import ZeroResults from "../common/ZeroResults"; +class IndividualSearchResultRow extends Component { + static propTypes = { + item: PropTypes.any.isRequired, + onResultRowPress: PropTypes.func.isRequired + } + + constructor(props, context) { + super(props, context); + } + + shouldComponentUpdate() { + return false; + } + + render() { + const {item, onResultRowPress} = this.props; + const individual = new Individual(item); + General.logDebug("IndividualSearchResultRow", `${individual.name}`); + return onResultRowPress(individual)} + background={TouchableNativeFeedback.SelectableBackground()}> + + + + ; + } +} + @Path('/individualSearchResults') class IndividualSearchResultsView extends AbstractComponent { static propTypes = { @@ -39,31 +61,23 @@ class IndividualSearchResultsView extends AbstractComponent { super.UNSAFE_componentWillMount(); } - renderRow(item, onResultRowPress) { - return onResultRowPress(new Individual(item))} - background={TouchableNativeFeedback.SelectableBackground()}> - - - - - } - render() { General.logDebug(this.viewName(), 'render'); - const dataSource = ListViewHelper.getDataSource(this.props.searchResults); const title = this.props.headerTitle || "searchResults"; + const searchResultsCollection = getUnderlyingRealmCollection(this.props.searchResults); return ( - + - this.renderRow(item, this.onResultRowPress.bind(this))}/> + item.uuid} + renderItem={({item}) => } + /> - + ); } diff --git a/packages/openchs-android/src/views/primitives/PresetOptionItem.js b/packages/openchs-android/src/views/primitives/PresetOptionItem.js index 47b991e8d..8b1d2c77b 100644 --- a/packages/openchs-android/src/views/primitives/PresetOptionItem.js +++ b/packages/openchs-android/src/views/primitives/PresetOptionItem.js @@ -1,4 +1,4 @@ -import {Text, TouchableOpacity, View, StyleSheet} from "react-native"; +import {StyleSheet, Text, TouchableOpacity} from "react-native"; import PropTypes from 'prop-types'; import React from "react"; import AbstractComponent from "../../framework/view/AbstractComponent"; @@ -6,7 +6,6 @@ import {Checkbox, Radio} from "native-base"; import Colors from '../primitives/Colors'; import _ from 'lodash'; import Styles from "./Styles"; -import UserInfoService from "../../service/UserInfoService"; class PresetOptionItem extends AbstractComponent { static defaultProps = { @@ -23,7 +22,8 @@ class PresetOptionItem extends AbstractComponent { style: PropTypes.object, chunked: PropTypes.bool, value: PropTypes.any, - radioItemPressed: PropTypes.func + radioItemPressed: PropTypes.func, + currentLocale: PropTypes.string }; static styles = StyleSheet.create({ @@ -56,7 +56,7 @@ class PresetOptionItem extends AbstractComponent { } render() { - const {value, checked, chunked, abnormal, style, validationResult, radioItemPressed, disabled} = this.props; + const {value, checked, chunked, abnormal, style, validationResult, radioItemPressed, disabled, currentLocale} = this.props; const color = _.isNil(validationResult) ? checked && abnormal @@ -72,7 +72,6 @@ class PresetOptionItem extends AbstractComponent { container: style }; const ToRender = chunked ? chunkedStyle : singleStyle; - const currentLocale = this.getService(UserInfoService).getUserSettings().locale; const isExtraHeightRequired = _.includes(['te_IN'], currentLocale); const extraLineHeight = isExtraHeightRequired ? {lineHeight: 20} : {}; const onRadioItemPress = _.isNil(radioItemPressed) ? null : () => radioItemPressed(value); diff --git a/packages/openchs-android/src/views/primitives/RadioGroup.js b/packages/openchs-android/src/views/primitives/RadioGroup.js index f7bab3b67..6e888eaae 100644 --- a/packages/openchs-android/src/views/primitives/RadioGroup.js +++ b/packages/openchs-android/src/views/primitives/RadioGroup.js @@ -9,6 +9,8 @@ import Distances from "./Distances"; import Styles from "./Styles"; import _ from 'lodash'; import ValidationErrorMessage from "../form/ValidationErrorMessage"; +import General from "../../utility/General"; +import UserInfoService from "../../service/UserInfoService"; export class RadioLabelValue { constructor(label, value, abnormal) { @@ -83,7 +85,7 @@ class RadioGroup extends AbstractComponent { }; } - renderPairedOptions(onRadioItemPressed) { + renderPairedOptions(onRadioItemPressed, currentLocale) { return _.chunk(this.props.labelValuePairs, 2).map((rlvPair, idx) => {rlvPair.map((rlv) => { @@ -96,6 +98,7 @@ class RadioGroup extends AbstractComponent { chunked={true} validationResult={this.props.validationError} key={rlv.label} + currentLocale={currentLocale} style={{ paddingVertical: Distances.VerticalSpacingBetweenOptionItems, paddingHorizontal: Distances.HorizontalSpacingBetweenOptionItems, @@ -109,7 +112,7 @@ class RadioGroup extends AbstractComponent { ); } - renderOptions(onRadioItemPressed) { + renderOptions(onRadioItemPressed, currentLocale) { return this.props.labelValuePairs.map(radioLabelValue => { let checked = this.props.selectionFn(radioLabelValue.value); let onRadioItemPress = checked ? onRadioItemPressed : null; @@ -118,6 +121,7 @@ class RadioGroup extends AbstractComponent { multiSelect={this.props.multiSelect} validationResult={this.props.validationError} key={radioLabelValue.label} + currentLocale={currentLocale} style={{ paddingVertical: Distances.VerticalSpacingBetweenOptionItems, paddingHorizontal: Distances.HorizontalSpacingBetweenOptionItems, @@ -170,25 +174,26 @@ class RadioGroup extends AbstractComponent { const mandatoryText = mandatory ? * : ; const GroupComponent = multiSelect ? Checkbox.Group : Radio.Group; + const currentLocale = this.getService(UserInfoService).getUserSettings().locale; //Do not replace null with noop as that would set a listener and not allow the message to prop up to higher level const onRadioValuePressed = (!multiSelect && allowRadioUnselect) ? this.onRadioValuePress.bind(this) : null; return ( - {!skipLabel && - {this.I18n.t(labelKey)}{mandatoryText}} - {labelValuePairs.length > 0 ? labelValuePairs.length === 1 && mandatory === true ? - - {this.renderSingleValue()} - : - this.onValueChanged(newValues)}> - {inPairs ? this.renderPairedOptions(onRadioValuePressed) : this.renderOptions(onRadioValuePressed)} - - : } - - - + {!skipLabel && + {this.I18n.t(labelKey)}{mandatoryText}} + {labelValuePairs.length > 0 ? labelValuePairs.length === 1 && mandatory === true ? + + {this.renderSingleValue()} + : + this.onValueChanged(newValues)}> + {inPairs ? this.renderPairedOptions(onRadioValuePressed, currentLocale) : this.renderOptions(onRadioValuePressed, currentLocale)} + + : } + + + ); } diff --git a/packages/openchs-android/src/views/primitives/Separator.js b/packages/openchs-android/src/views/primitives/Separator.js index a66e61ba7..c532595f2 100644 --- a/packages/openchs-android/src/views/primitives/Separator.js +++ b/packages/openchs-android/src/views/primitives/Separator.js @@ -30,4 +30,4 @@ class Separator extends AbstractComponent { } } -export default Separator; \ No newline at end of file +export default Separator;