Skip to content

Commit

Permalink
#1107 | Suhas/Joy | Remove structured-clone serialization of CustomDa…
Browse files Browse the repository at this point in the history
…shboardCache fields

Removed @ungap/structured-clone as a dependency.
Added General.deepOmit function to remove specific key(s) in a nested object. Helps prevent cyclic reference errors during JSON.stringify.
  • Loading branch information
1t5j0y committed Sep 28, 2023
1 parent 40614de commit 617ade8
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 39 deletions.
31 changes: 7 additions & 24 deletions packages/openchs-android/package-lock.json

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

3 changes: 1 addition & 2 deletions packages/openchs-android/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"@react-native-cookies/cookies": "^6.2.1",
"@react-native-firebase/analytics": "15.2.0",
"@react-native-firebase/app": "15.2.0",
"@ungap/structured-clone": "1.2.0",
"amazon-cognito-identity-js": "6.3.1",
"avni-health-modules": "^0.0.19",
"base-64": "^1.0.0",
Expand All @@ -58,7 +57,7 @@
"lodash": "4.17.21",
"moment": "2.29.4",
"native-base": "3.4.9",
"openchs-models": "1.30.69",
"openchs-models": "1.30.71",
"prop-types": "15.8.1",
"react": "18.2.0",
"react-native": "0.72.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import General from "../../utility/General";
import DashboardFilterService from "../../service/reports/DashboardFilterService";
import CustomDashboardCacheService from '../../service/CustomDashboardCacheService';
import CryptoUtils from '../../utility/CryptoUtils';
import {serialize} from '@ungap/structured-clone';

class CustomDashboardActions {

Expand Down Expand Up @@ -58,7 +57,7 @@ class CustomDashboardActions {
const dashboardFilterService = context.get(DashboardFilterService);
const customDashboardCacheService = context.get(CustomDashboardCacheService);
const filterConfigs = dashboardFilterService.getFilterConfigsForDashboard(newState.activeDashboardUUID);
let filterConfigsJSON = JSON.stringify(serialize(filterConfigs));
let filterConfigsJSON = JSON.stringify(filterConfigs);
let filterConfigsChecksum = CryptoUtils.computeHash(filterConfigsJSON);
const cachedData = customDashboardCacheService.fetchCachedData(newState.activeDashboardUUID, filterConfigsChecksum);
newState.filterConfigsChecksum = cachedData.getChecksum();
Expand Down
26 changes: 15 additions & 11 deletions packages/openchs-android/src/action/mydashboard/FiltersActionsV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {CustomDashboardActions} from '../customDashboard/CustomDashboardActions'
import CustomDashboardCacheService from '../../service/CustomDashboardCacheService';
import CryptoUtils from '../../utility/CryptoUtils';

import {serialize} from '@ungap/structured-clone';
import General from "../../utility/General";

class FiltersActionsV2 {
static getInitialState() {
Expand All @@ -26,7 +26,7 @@ class FiltersActionsV2 {
const filterConfigs = dashboardFilterService.getFilterConfigsForDashboard(action.dashboardUUID);
const filters = dashboardFilterService.getFilters(action.dashboardUUID);
let newState = {...state, filterConfigs: filterConfigs, filters: filters, loading: false};
let filterConfigsJSON = JSON.stringify(serialize(newState.filterConfigs));
let filterConfigsJSON = JSON.stringify(newState.filterConfigs);
newState.filterConfigsChecksum = CryptoUtils.computeHash(filterConfigsJSON);
const cachedData = context.get(CustomDashboardCacheService).fetchCachedData(action.dashboardUUID, newState.filterConfigsChecksum);
if(state.dashboardUUID !== action.dashboardUUID) {
Expand Down Expand Up @@ -57,6 +57,8 @@ class FiltersActionsV2 {
break;

case CustomFilter.type.Address:
updatedValue = General.deepOmit(value, 'locationMappings'); //including locationMappings causes cyclical reference errors during JSON.stringify
break;
case Concept.dataType.Subject:
case Concept.dataType.Text :
case Concept.dataType.Notes :
Expand Down Expand Up @@ -136,13 +138,15 @@ class FiltersActionsV2 {
break;
default:
let customConceptValue = [{value: currentFilterValue}];
if(filterConfig.widget === CustomFilter.widget.Range) {
customConceptValue = [{dateType: filterConfig.type,
if(_.get(filterConfig, 'widget') === CustomFilter.widget.Range) {
customConceptValue = [{dateType: _.get(filterConfig, 'type'),
minValue: currentFilterValue.minValue,
maxValue: currentFilterValue.maxValue}];
}
selectedFilters.selectedCustomFilters = {...selectedFilters.selectedCustomFilters,
[filterConfig.observationBasedFilter.concept.name] : customConceptValue};
if (!_.isEmpty(_.get(filterConfig, 'observationBasedFilter.concept.name'))) {
selectedFilters.selectedCustomFilters = {...selectedFilters.selectedCustomFilters,
[_.get(filterConfig, 'observationBasedFilter.concept.name')] : customConceptValue};
}
break;
}

Expand All @@ -158,7 +162,7 @@ class FiltersActionsV2 {
const filledFilterValues = _.filter(Object.entries(selectedValues), ([, filterValue]) => !ModelGeneral.isDeepEmpty(filterValue));
//Check if there are errors in filter values specified
filledFilterValues.forEach(([filterUUID, filterValue]) => {
const [success, message] = filterConfigs[filterUUID].validate(filterValue);
const [success, message] = filterConfigs[filterUUID].validate && filterConfigs[filterUUID].validate(filterValue) || [false, `validate for filterConfig ${filterUUID} not found`];
if (!success)
newState.filterErrors[filterUUID] = message;
});
Expand All @@ -181,10 +185,10 @@ class FiltersActionsV2 {
}

static createCustomDashboardCache(newState, dashboardUUID, transformedFilters, ruleInputArray) {
let selectValueJSON = JSON.stringify(serialize(newState.selectedValues));
let filteredErrorsJSON = JSON.stringify(serialize(newState.filterErrors));
let transformedFiltersJSON = JSON.stringify(serialize(transformedFilters));
let ruleInputJSON = JSON.stringify(serialize({ruleInputArray: ruleInputArray}));
let selectValueJSON = JSON.stringify(newState.selectedValues);
let filteredErrorsJSON = JSON.stringify(newState.filterErrors);
let transformedFiltersJSON = JSON.stringify(transformedFilters);
let ruleInputJSON = JSON.stringify({ruleInputArray: ruleInputArray});
const customDashboardCache = CustomDashboardCache.create(dashboardUUID, newState.filterConfigsChecksum, new Date(),
selectValueJSON, newState.filterApplied, filteredErrorsJSON, ruleInputJSON, transformedFiltersJSON);
return customDashboardCache;
Expand Down
17 changes: 17 additions & 0 deletions packages/openchs-android/src/utility/General.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,23 @@ class General {
static clearClipboard() {
Clipboard.setString('');
}

//from https://stackoverflow.com/questions/39085399/lodash-remove-items-recursively
static deepOmit(obj, keysToOmit) {
const keysToOmitIndex = _.keyBy(Array.isArray(keysToOmit) ? keysToOmit : [keysToOmit] ); // create an index object of the keys that should be omitted

function omitFromObject(obj) { // the inner function which will be called recursivley
return _.transform(obj, function(result, value, key) { // transform to a new object
if (key in keysToOmitIndex) { // if the key is in the index skip it
return;
}

result[key] = _.isObject(value) ? omitFromObject(value) : value; // if the key is an object run it through the inner function - omitFromObject
})
}

return omitFromObject(obj); // return the inner function result
}
}

export default General;

0 comments on commit 617ade8

Please sign in to comment.