diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be56c7e9b..5012a23d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,10 +25,10 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Run unit tests with Gradle - run: ./gradlew :android-json-form-wizard:clean :android-json-form-wizard:jacocoTestReport --stacktrace + run: ./gradlew :android-json-form-wizard:clean :android-json-form-wizard:jacocoTestReport --stacktrace -Dorg.gradle.jvmargs="-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError" - name: Upload coverage to Coveralls with Gradle run: ./gradlew coveralls --stacktrace env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }} - name: Generate Javadoc with Gradle - run: ./gradlew javadoc + run: ./gradlew javadoc \ No newline at end of file diff --git a/android-json-form-wizard/build.gradle b/android-json-form-wizard/build.gradle index 1fa5c2320..709beae15 100644 --- a/android-json-form-wizard/build.gradle +++ b/android-json-form-wizard/build.gradle @@ -53,6 +53,7 @@ android { lintOptions { abortOnError false + checkReleaseBuilds false } testOptions { diff --git a/android-json-form-wizard/src/main/assets/app.properties b/android-json-form-wizard/src/main/assets/app.properties new file mode 100644 index 000000000..a2e8a9e3a --- /dev/null +++ b/android-json-form-wizard/src/main/assets/app.properties @@ -0,0 +1,2 @@ +widget.datepicker.is.numeric=true +widget.value.translated=true \ No newline at end of file diff --git a/android-json-form-wizard/src/main/assets/json.form/basic_form.json b/android-json-form-wizard/src/main/assets/json.form/basic_form.json new file mode 100644 index 000000000..4fcc1c20b --- /dev/null +++ b/android-json-form-wizard/src/main/assets/json.form/basic_form.json @@ -0,0 +1,580 @@ +{ + "count": "3", + "encounter_type": "Test", + "entity_id": "", + "relational_id": "", + "validate_on_submit": true, + "show_errors_on_submit": true, + "metadata": { + "start": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "start", + "openmrs_entity_id": "163137AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "end": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "end", + "openmrs_entity_id": "163138AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "today": { + "openmrs_entity_parent": "", + "openmrs_entity": "encounter", + "openmrs_entity_id": "encounter_date" + }, + "deviceid": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "deviceid", + "openmrs_entity_id": "163149AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "subscriberid": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "subscriberid", + "openmrs_entity_id": "163150AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "simserial": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "simserial", + "openmrs_entity_id": "163151AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "phonenumber": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "phonenumber", + "openmrs_entity_id": "163152AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "encounter_location": "", + "look_up": { + "entity_id": "", + "value": "" + } + }, + "step1": { + "title": "Basic Form One", + "next": "step2", + "fields": [ + { + "key": "user_image", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "choose_image", + "uploadButtonText": "Take a photo of the child" + }, + { + "key": "finger_print", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "finger_print", + "project_id": "tZqJnw0ajK04LMYdZzyw", + "user_id": "test_user", + "module_id": "mpower", + "finger_print_option": "register", + "uploadButtonText": "Take finger print", + "image_file": "", + "relevance": { + "step1:user_first_name": { + "type": "string", + "ex": "equalTo(., \"test\")" + } + } + }, + { + "key": "finger_print", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "finger_print", + "project_id": "tZqJnw0ajK04LMYdZzyw", + "user_id": "test_user", + "module_id": "mpower", + "gu_id": "id", + "finger_print_option": "verify", + "uploadButtonText": "Verify finger print", + "image_file": "" + }, + + { + "key": "Sex", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "spinner", + "hint": "hint", + "options": [ + { + "key": "male", + "text": "male", + "openmrs_entity": "", + "openmrs_entity_id": "" + }, + { + "key": "female", + "text": "female", + "openmrs_entity": "", + "openmrs_entity_id": "" + } + ], + "v_required": { + "value": "true", + "err": "please select the gender" + } + }, + { + "key": "user_first_name", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "edit_text", + "hint": "User First name", + "edit_type": "name", + "v_required": { + "value": "true", + "err": "Please enter the first name" + }, + "v_regex": { + "value": "[A-Za-z\\s\\.\\-]*", + "err": "Please enter a valid name" + } + }, + { + "key": "user_last_name", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "edit_text", + "hint": "User Last name", + "edit_type": "name", + "v_required": { + "value": "true", + "err": "Please enter the last name" + }, + "v_regex": { + "value": "[A-Za-z\\s\\.\\-]*", + "err": "Please enter a valid name" + }, + "relevance": { + "step1:user_first_name": { + "type": "string", + "ex": "equalTo(., \"test\")" + } + } + }, + { + "key": "user_qr_code", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "barcode", + "barcode_type": "qrcode", + "hint": "User ID", + "scanButtonText": "Scan QR Code", + "v_numeric": { + "value": "true", + "err": "Please enter a valid ID" + }, + "v_required": { + "value": false, + "err": "Please enter the user ID" + } + }, + { + "key": "user_age", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "edit_text", + "hint": "User age", + "edit_type": "name", + "v_required": { + "value": "true", + "err": "Please enter the last name" + }, + "v_regex": { + "value": "[A-Za-z\\s\\.\\-]*", + "err": "Please enter a valid name" + } + }, + { + "key": "user_gps", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "openmrs_data_type": "text", + "type": "gps" + }, + { + "key": "user_calculation_one", + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_entity_id": "165260AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "type": "hidden" + } + ] + }, + "step2": { + "title": "Basic Form Two", + "next": "step3", + "fields": [ + { + "key": "user_select", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "native_radio", + "label": "Do you want to select anything", + "label_text_style": "bold", + "text_color": "#000000", + "label_info_text": "You can select every thing you want.", + "label_info_title": "User selection", + "options": [ + { + "key": "yes", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "text": "Yes" + }, + { + "key": "no", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "text": "No" + } + ] + }, + { + "key": "user_normal_edit_text", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "normal_edit_text", + "hint": "User Text ", + "edit_text_style": "bordered", + "v_required": { + "value": true, + "err": "Please enter the user ID" + } + }, + { + "key": "user_normal_edit_number", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "normal_edit_text", + "hint": "User number", + "edit_text_style": "bordered", + "edit_type": "number", + "v_required": { + "value": true, + "err": "Please enter the user ID" + } + }, + { + "key": "user_toaster_problem", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "toaster_notes", + "text": "User problem toaster", + "toaster_info_text": "Procedure:\n- This shows the user the problems.\n- Problem toaster.", + "toaster_type": "problem" + }, + { + "key": "user_toaster_warning", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "toaster_notes", + "text": "User warning toaster", + "toaster_info_text": "Procedure:\n- This shows the user the warning.\n- Warning toaster.", + "toaster_type": "warning" + }, + { + "key": "user_toaster_positive", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "toaster_notes", + "text": "User positive toaster", + "toaster_info_text": "Procedure:\n- This shows the user the positive.\n- Positive toaster.", + "toaster_type": "positive" + }, + { + "key": "user_toaster_info", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "toaster_notes", + "text": "User Info toaster", + "toaster_info_text": "Procedure:\n- This shows the user the info.\n- Info toaster.", + "toaster_type": "info" + } + ] + }, + "step3": { + "title": "Basic Form Threes", + "fields": [ + { + "key": "user_date", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "date_picker", + "hint": "User DOB", + "expanded": false, + "duration": { + "label": "Age" + }, + "default": "12-12-2015", + "min_date": "today-5y", + "max_date": "today", + "v_required": { + "value": "true", + "err": "Please enter the date of birth" + } + }, + { + "key": "user_time", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "time_picker", + "hint": "Birth Time", + "expanded": false, + "duration": { + "label": "Birth Time" + }, + "v_required": { + "value": true, + "err": "Please enter the time of birth" + } + }, + { + "key": "user_spinner", + "openmrs_entity": "openmrs_entity", + "openmrs_entity_id": "openmrs_entity_id", + "openmrs_entity_parent": "openmrs_entity_parent", + "type": "spinner", + "hint": "User Spinners", + "values": [ + "User Option One", + "User Option Two" + ], + "keys": [ + "user_option_one", + "user_option_two" + ], + "v_required": { + "value": "true", + "err": "Please enter the sex" + }, + "openmrs_choice_ids": { + "user_one": "1107AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "user_two": "1713AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + }, + "value": "user_one" + }, + { + "key": "response_spinner_with_options", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "spinner", + "hint": "Response Spinners", + "options": [ + { + "key": "yes", + "text": "Yes", + "openmrs_entity": "", + "openmrs_entity_id": "", + "openmrs_entity_parent": "" + }, + { + "key": "no", + "text": "No", + "openmrs_entity": "openmrs_entity", + "openmrs_entity_id": "openmrs_entity_id", + "openmrs_entity_parent": "openmrs_entity_parent" + }, + { + "key": "maybe", + "text": "Maybe", + "openmrs_entity": "openmrs_entity_2", + "openmrs_entity_id": "openmrs_entity_id_2", + "openmrs_entity_parent": "openmrs_entity_parent_2" + } + ], + "value": "maybe", + "v_required": { + "value": "true", + "err": "Please enter response" + } + }, + { + "key": "response_spinner_with_options", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "spinner", + "hint": "Response Spinners", + "options": [ + { + "key": "yes", + "text": "Yes", + "value": false, + "openmrs_entity": "", + "openmrs_entity_id": "" + }, + { + "key": "no", + "text": "No", + "value": false, + "openmrs_entity": "", + "openmrs_entity_id": "" + }, + { + "key": "maybe", + "text": "Maybe", + "value": false, + "openmrs_entity": "", + "openmrs_entity_id": "" + } + ], + "v_required": { + "value": "true", + "err": "Please enter response" + }, + "openmrs_choice_ids": { + "user_one": "1107AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "user_two": "1713AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + } + }, + { + "key": "spacer", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "spacer", + "type": "spacer", + "spacer_height": "20dp" + }, + { + "key": "user_form_labels", + "type": "label", + "label_text_style": "bold", + "text": "Number of labels", + "text_color": "#000000", + "v_required": { + "value": true + } + }, + { + "key": "user_form", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "numbers_selector", + "number_of_selectors": "5", + "start_number": "1", + "max_value": "15", + "text_size": "16px", + "text_color": "#000000", + "selected_text_color": "#ffffff", + "v_required": { + "value": true + } + }, + { + "key": "spacer", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "spacer", + "type": "spacer", + "spacer_height": "20dp" + }, + { + "key": "user_sub_form", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "native_radio", + "label": "User sub forms?", + "label_text_style": "bold", + "text_color": "#000000", + "extra_rel": true, + "has_extra_rel": "yes", + "options": [ + { + "key": "yes", + "text": "Yes", + "value": false, + "openmrs_entity": "", + "openmrs_entity_id": "", + "specify_info": "User sub specify...", + "specify_widget": "normal_edit_text", + "specify_info_color": "#8C8C8C", + "secondary_suffix": "bpm", + "content_form": "user_native_sub_form" + }, + { + "key": "no", + "text": "No", + "value": false, + "openmrs_entity": "", + "openmrs_entity_id": "" + } + ], + "v_required": { + "value": true, + "err": "Please specify user native form." + } + }, + { + "key": "user_check_box", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "openmrs_data_type": "select one", + "type": "check_box", + "label": "Do want to select any checkbox?", + "label_text_style": "bold", + "options": [ + { + "key": "None", + "text": "None", + "value": false, + "openmrs_choice_id": "" + }, + { + "key": "yes", + "text": "Yes", + "value": false, + "openmrs_choice_id": "" + }, + { + "key": "no", + "text": "No", + "value": false, + "openmrs_choice_id": "" + }, + { + "key": "other", + "text": "Other", + "value": false, + "openmrs_choice_id": "" + } + ], + "v_required": { + "value": "false" + }, + "value": "[yes]" + } + ] + } +} \ No newline at end of file diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/activities/JsonFormActivity.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/activities/JsonFormActivity.java index 857b721d3..42287b5d2 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/activities/JsonFormActivity.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/activities/JsonFormActivity.java @@ -1,5 +1,9 @@ package com.vijay.jsonwizard.activities; +import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS; +import static com.vijay.jsonwizard.utils.FormUtils.getCheckboxValueJsonArray; +import static com.vijay.jsonwizard.utils.FormUtils.getCurrentCheckboxValues; + import android.Manifest; import android.annotation.SuppressLint; import android.app.AlertDialog; @@ -14,11 +18,6 @@ import android.graphics.drawable.GradientDrawable; import android.os.AsyncTask; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; -import androidx.core.util.Pair; -import androidx.appcompat.widget.AppCompatRadioButton; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; @@ -37,6 +36,12 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatRadioButton; +import androidx.core.app.ActivityCompat; +import androidx.core.util.Pair; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.rengwuxian.materialedittext.MaterialEditText; @@ -68,6 +73,7 @@ import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.utils.ExObjectResult; import com.vijay.jsonwizard.utils.FormUtils; +import com.vijay.jsonwizard.utils.NativeFormsProperties; import com.vijay.jsonwizard.utils.PermissionUtils; import com.vijay.jsonwizard.utils.PropertyManager; import com.vijay.jsonwizard.utils.Utils; @@ -102,38 +108,20 @@ import timber.log.Timber; -import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS; -import static com.vijay.jsonwizard.utils.FormUtils.getCheckboxValueJsonArray; -import static com.vijay.jsonwizard.utils.FormUtils.getCurrentCheckboxValues; - public class JsonFormActivity extends JsonFormBaseActivity implements JsonApi { - private FormUtils formUtils = new FormUtils(); - private Map formDataViews = new ConcurrentHashMap<>(); - private Map formFields = new ConcurrentHashMap<>(); - private Set popupFormFields = new ConcurrentSkipListSet<>(); - private String functionRegex; - private HashMap comparisons; - private Map> ruleKeys = new HashMap<>(); - private GenericDialogInterface genericDialogInterface; - private JSONArray extraFieldsWithValues; - private Map formValuesCacheMap = new HashMap<>(); - private TextView selectedTextView = null; - private Utils utils = new Utils(); - private HashMap addressMap = new HashMap<>(); - - private Map> calculationDependencyMap = new HashMap<>(); - private Map> skipLogicDependencyMap = new HashMap<>(); - - private Map stepSkipLogicPresenceMap = new ConcurrentHashMap<>(); - - private boolean isNextStepRelevant; - - private String nextStep = ""; - - private AppExecutors appExecutors = new AppExecutors(); - - private BroadcastReceiver messageReceiver = new BroadcastReceiver() { + private final FormUtils formUtils = new FormUtils(); + private final Map formFields = new ConcurrentHashMap<>(); + private final Set popupFormFields = new ConcurrentSkipListSet<>(); + private final Map> ruleKeys = new HashMap<>(); + private final Map formValuesCacheMap = new HashMap<>(); + private final Utils utils = new Utils(); + private final HashMap addressMap = new HashMap<>(); + private final Map> calculationDependencyMap = new HashMap<>(); + private final Map> skipLogicDependencyMap = new HashMap<>(); + private final Map stepSkipLogicPresenceMap = new ConcurrentHashMap<>(); + private final AppExecutors appExecutors = new AppExecutors(); + private final BroadcastReceiver messageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String messageType = intent.getStringExtra(JsonFormConstants.INTENT_KEY.MESSAGE_TYPE); @@ -147,6 +135,15 @@ public void onReceive(Context context, Intent intent) { } } }; + private Map formDataViews = new ConcurrentHashMap<>(); + private String functionRegex; + private HashMap comparisons; + private GenericDialogInterface genericDialogInterface; + private JSONArray extraFieldsWithValues; + private TextView selectedTextView = null; + private boolean isNextStepRelevant; + private String nextStep = ""; + public void performActionOnReceived(String stepName) { try { @@ -342,7 +339,6 @@ public void refreshSkipLogic(String parentKey, String childKey, boolean popup, S } } - public Pair getCalculationAddressAndValue(View view) throws JSONException { String calculationTag = (String) view.getTag(R.id.calculation); String widgetKey = (String) view.getTag(R.id.key); @@ -376,35 +372,42 @@ public Pair getCalculationAddressAndValue(View view) throw @Override public void refreshCalculationLogic(String parentKey, String childKey, boolean popup, String stepName, boolean isForNextStep) { - Set viewsIds = calculationDependencyMap.get(stepName + "_" + parentKey); - if (parentKey == null || viewsIds == null) - viewsIds = calculationLogicViews.keySet(); - for (String viewId : viewsIds) { - try { - View curView = calculationLogicViews.get(viewId); - if (curView == null) { - Timber.w("calculationLogicViews Missing %s", viewId); - continue; - } - Pair addressAndValue = getCalculationAddressAndValue(curView); - if (addressAndValue != null && addressAndValue.first != null) { - String[] address = addressAndValue.first; - JSONObject valueSource = addressAndValue.second; - Facts curValueMap; - if (valueSource.length() > 0) { - curValueMap = getValueFromAddress(address, popup, valueSource); - } else { - curValueMap = getValueFromAddress(address, popup); + appExecutors.diskIO().execute(() ->{ + Set viewsIds = calculationDependencyMap.get(stepName + "_" + parentKey); + if (parentKey == null || viewsIds == null) + viewsIds = calculationLogicViews.keySet(); + for (String viewId : viewsIds) { + try { + View curView = calculationLogicViews.get(viewId); + if (curView == null) { + Timber.w("calculationLogicViews Missing %s", viewId); + continue; } - //update ui - updateCalculation(curValueMap, curView, address, isForNextStep); - } + Pair addressAndValue = getCalculationAddressAndValue(curView); + if (addressAndValue != null && addressAndValue.first != null) { + String[] address = addressAndValue.first; + JSONObject valueSource = addressAndValue.second; + Facts curValueMap; + if (valueSource.length() > 0) { + curValueMap = getValueFromAddress(address, popup, valueSource); + } else { + curValueMap = getValueFromAddress(address, popup); + } + //update ui + appExecutors.mainThread().execute(() -> { + updateCalculation(curValueMap, curView, address, isForNextStep); + }); - } catch (Exception e) { - Timber.e(e, "%s refreshCalculationLogic()", this.getClass().getCanonicalName()); + } + + } catch (Exception e) { + Timber.e(e, "%s refreshCalculationLogic()", this.getClass().getCanonicalName()); + } } - } + + }); + } @Override @@ -626,24 +629,27 @@ public JSONObject getObjectUsingAddress(String[] address, boolean popup, JSONObj */ @Override public void refreshConstraints(String parentKey, String childKey, boolean popup) { - initComparisons(); + appExecutors.diskIO().execute(()->{ + initComparisons(); - // Priorities constraints on the view that has just been changed - String changedViewKey = parentKey; - if (changedViewKey != null && childKey != null) { - changedViewKey = changedViewKey + ":" + childKey; - } + // Priorities constraints on the view that has just been changed + String changedViewKey = parentKey; + if (changedViewKey != null && childKey != null) { + changedViewKey = changedViewKey + ":" + childKey; + } - if (changedViewKey != null && (constrainedViews != null && constrainedViews.containsKey(changedViewKey))) { - checkViewConstraints(constrainedViews.get(changedViewKey), popup); - } + if (changedViewKey != null && (constrainedViews != null && constrainedViews.containsKey(changedViewKey))) { + checkViewConstraints(constrainedViews.get(changedViewKey), popup); + } - for (View curView : constrainedViews.values()) { - String viewKey = getViewKey(curView); - if (changedViewKey == null || (!TextUtils.isEmpty(viewKey) && !viewKey.equals(changedViewKey))) { - checkViewConstraints(curView, popup); + for (View curView : constrainedViews.values()) { + String viewKey = getViewKey(curView); + if (changedViewKey == null || (!TextUtils.isEmpty(viewKey) && !viewKey.equals(changedViewKey))) { + checkViewConstraints(curView, popup); + } } - } + }); + } @Override @@ -719,7 +725,6 @@ protected void initiateFormUpdate(JSONObject json) { } } - @Override public void updateGenericPopupSecondaryValues(JSONArray jsonArray, String stepName) { if (jsonArray == null || jsonArray.length() == 0) { @@ -899,7 +904,11 @@ private void getFieldObject(String stepName, List rulesList, JSONArray r String value; if (JsonFormConstants.CHECK_BOX.equals(fieldObject.getString(JsonFormConstants.TYPE))) { value = String.valueOf(fieldObject.getJSONArray(JsonFormConstants.VALUES)); - fieldObject.put(JsonFormConstants.VALUE, value); + if (Utils.enabledProperty(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)) { + fieldObject.put(JsonFormConstants.VALUE, Utils.generateTranslatableValue(value, fieldObject)); + } else { + fieldObject.put(JsonFormConstants.VALUE, value); + } } else { value = fieldObject.getJSONArray(JsonFormConstants.VALUES).getString(0); fieldObject.put(JsonFormConstants.VALUE, value); @@ -947,11 +956,37 @@ private void widgetWriteItemValue(String value, JSONObject item, String itemType if (!TextUtils.isEmpty(value)) { value = value.trim(); } - item.put(JsonFormConstants.VALUE, itemType.equals(JsonFormConstants.HIDDEN) && TextUtils.isEmpty(value) ? - item.has(JsonFormConstants.VALUE) && !TextUtils.isEmpty(item.getString(JsonFormConstants.VALUE)) ? - item.getString(JsonFormConstants.VALUE) : value : value); + if (itemType.equals(JsonFormConstants.HIDDEN) && TextUtils.isEmpty(value)) { + if (item.has(JsonFormConstants.VALUE) && !TextUtils.isEmpty(item.getString(JsonFormConstants.VALUE))) + item.put(JsonFormConstants.VALUE, item.getString(JsonFormConstants.VALUE)); + else item.put(JsonFormConstants.VALUE, value); + } else { + if ((itemType.equals(JsonFormConstants.NATIVE_RADIO_BUTTON) || itemType.equals(JsonFormConstants.SPINNER) || itemType.equals(JsonFormConstants.CHECK_BOX)) && Utils.enabledProperty(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)) { + if (itemType.equals(JsonFormConstants.SPINNER)) { + if (item.has(JsonFormConstants.KEYS) && item.has(JsonFormConstants.VALUES)) { + item.put(JsonFormConstants.VALUE, value); + } else { + item.put(JsonFormConstants.VALUE, Utils.generateTranslatableValue(value, item)); + } + } else { + item.put(JsonFormConstants.VALUE, Utils.generateTranslatableValue(value, item)); + } + } else { + item.put(JsonFormConstants.VALUE, value); + } + } } + /** + * Generates a JSONObject Value for the value translatable fields + * + * @param value + * @param item + * @param itemType + * @return + */ + + private boolean checkPopUpValidity(String[] curKey, boolean popup) throws JSONException { boolean validity = false; if (popup) { @@ -1020,9 +1055,19 @@ protected void checkBoxWriteValue(String stepName, String parentKey, String chil childKey.equals(option.getString(JsonFormConstants.KEY))) { option.put(JsonFormConstants.VALUE, Boolean.parseBoolean(value)); if (Boolean.parseBoolean(value)) { - currentValues.add(childKey); + if (Utils.enabledProperty(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)) { + JSONObject object = Utils.generateTranslatableValue(childKey, option); + currentValues.add(object.toString()); + } else { + currentValues.add(childKey); + } } else { - currentValues.remove(childKey); + if (Utils.enabledProperty(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)) { + JSONObject object = Utils.generateTranslatableValue(childKey, option); + currentValues.remove(object.toString()); + } else { + currentValues.remove(childKey); + } } } } @@ -1092,7 +1137,8 @@ protected void onResume() { } - protected Pair getRelevanceAddress(View view, boolean popup) throws JSONException { + protected Pair getRelevanceAddress(View view, boolean popup) throws + JSONException { if (view != null) { String relevanceTag = (String) view.getTag(R.id.relevance); String widgetKey = (String) view.getTag(R.id.key); @@ -1283,7 +1329,8 @@ private void checkViewConstraints(View curView, boolean popup) { } } - private void updateUiByConstraints(View curView, boolean popup, String errorMessage) throws JSONException { + private void updateUiByConstraints(View curView, boolean popup, String errorMessage) throws + JSONException { String[] address = ((String) curView.getTag(R.id.address)).split(":"); if (errorMessage != null) { if (curView instanceof MaterialEditText) { @@ -1807,8 +1854,12 @@ private boolean isRelevant(Facts curValueMap, JSONObject curRelevance) throws Ex } return false; } else { - String curValue = String.valueOf(curValueMap.get(JsonFormConstants.VALUE)); - return doComparison(curValue != null ? curValue : "", curRelevance); + Object currObjectValue = curValueMap.get(JsonFormConstants.VALUE); + if (currObjectValue != null) { + String curValue = String.valueOf(currObjectValue); + return doComparison(curValue, curRelevance); + } + return doComparison("", curRelevance); } } return false; @@ -1970,7 +2021,8 @@ public void run() { } - private void updateCalculation(Facts valueMap, View view, String[] address, boolean isForNextStep) { + private void updateCalculation(Facts valueMap, View view, String[] address, + boolean isForNextStep) { String calculation; try { if (address[0].equals(RuleConstant.RULES_DYNAMIC)) { @@ -2104,8 +2156,7 @@ protected Object getValue(JSONObject object) throws JSONException { Object value; if (object.has(JsonFormConstants.VALUE)) { - value = object.opt(JsonFormConstants.VALUE); - + value = Utils.getValueAfterTranslation(object); if (isNumberWidget(object)) { value = TextUtils.isEmpty(object.optString(JsonFormConstants.VALUE)) ? 0 : processNumberValues(object.optString(JsonFormConstants.VALUE)); } else if (value != null && !TextUtils.isEmpty(object.getString(JsonFormConstants.VALUE)) && canHaveNumber(object)) { @@ -2467,6 +2518,10 @@ public boolean isNextStepRelevant() { return isNextStepRelevant; } + public void setNextStepRelevant(boolean nextStepRelevant) { + isNextStepRelevant = nextStepRelevant; + } + @Override public String nextStep() { return nextStep; @@ -2477,10 +2532,6 @@ public void setNextStep(String nextStep) { this.nextStep = nextStep; } - public void setNextStepRelevant(boolean nextStepRelevant) { - isNextStepRelevant = nextStepRelevant; - } - @Override public Map getFormFieldsMap() { return formFields; diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/constants/JsonFormConstants.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/constants/JsonFormConstants.java index ef4fa5753..c2cb18ec5 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/constants/JsonFormConstants.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/constants/JsonFormConstants.java @@ -237,6 +237,7 @@ public class JsonFormConstants { public static final String PROPERTIES_FILE_EXTENSION = ".properties"; public static final String JSON_FILE_EXTENSION = ".json"; public static final String CLIENT_FORM_ASSET_VERSION = "base version"; + public static final String TRANSLATION_TEXT = "translation_text"; public interface MultiSelectUtils { String IS_HEADER = "isHeader"; diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/customviews/GenericPopupDialog.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/customviews/GenericPopupDialog.java index 750046a3d..f09dd21a3 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/customviews/GenericPopupDialog.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/customviews/GenericPopupDialog.java @@ -1,12 +1,13 @@ package com.vijay.jsonwizard.customviews; +import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS; + import android.app.Activity; import android.app.DialogFragment; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import androidx.annotation.Nullable; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -16,6 +17,8 @@ import android.widget.Button; import android.widget.LinearLayout; +import androidx.annotation.Nullable; + import com.vijay.jsonwizard.NativeFormLibrary; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; @@ -43,8 +46,6 @@ import timber.log.Timber; -import static android.view.inputmethod.InputMethodManager.HIDE_NOT_ALWAYS; - public class GenericPopupDialog extends DialogFragment implements GenericDialogInterface { private ViewGroup dialogView; private JsonFormInteractor jsonFormInteractor = JsonFormInteractor.getInstance(); @@ -89,51 +90,50 @@ public void onActivityCreated(Bundle savedInstanceState) { "The Context is not set. Did you forget to set context with Generic Dialog setContext method?"); } - getJsonApi().getAppExecutors().diskIO().execute(new Runnable() { - @Override - public void run() { + getJsonApi().getAppExecutors().diskIO().execute(() -> { + getJsonApi().getAppExecutors().mainThread().execute(() -> { + }); - if (isDetached()) { - return; - } - // support translation of sub-forms - // support translation of sub-forms - Intent activityIntent = getActivity().getIntent(); - translateSubForm = activityIntent != null && activityIntent.hasExtra(JsonFormConstants.PERFORM_FORM_TRANSLATION) ? - activityIntent.getBooleanExtra(JsonFormConstants.PERFORM_FORM_TRANSLATION, false) : - NativeFormLibrary.getInstance().isPerformFormTranslation(); + if (isDetached()) { + return; + } + // support translation of sub-forms + // support translation of sub-forms + Intent activityIntent = getActivity().getIntent(); + translateSubForm = activityIntent != null && activityIntent.hasExtra(JsonFormConstants.PERFORM_FORM_TRANSLATION) ? + activityIntent.getBooleanExtra(JsonFormConstants.PERFORM_FORM_TRANSLATION, false) : + NativeFormLibrary.getInstance().isPerformFormTranslation(); - try { - setMainFormFields(formUtils.getFormFields(getStepName(), context)); - loadPartialSecondaryValues(); - createSecondaryValuesMap(); + try { + setMainFormFields(formUtils.getFormFields(getStepName(), context)); + loadPartialSecondaryValues(); + createSecondaryValuesMap(); - loadSubForms(); + loadSubForms(); - getJsonApi().updateGenericPopupSecondaryValues(specifyContent, stepName); - } catch (JSONException e) { - Timber.e(e, " --> onCreate"); - } + getJsonApi().updateGenericPopupSecondaryValues(specifyContent, stepName); + } catch (JSONException e) { + Timber.e(e, " --> onCreate"); + } - final List views = initiateViews(); - if (isDetached()) { - return; - } - getJsonApi().initializeDependencyMaps(); - getJsonApi().getAppExecutors().mainThread().execute(new Runnable() { - @Override - public void run() { - if (isDetached()) { - return; - } - setViewList(views); - getJsonApi().invokeRefreshLogic(null, true, null, null, getStepName(), false); - if (getDialogView() != null) { - addWidgetViews(getDialogView()); - } - } - }); + final List views = initiateViews(); + if (isDetached()) { + return; } + getJsonApi().initializeDependencyMaps(); + getJsonApi().getAppExecutors().mainThread().execute(new Runnable() { + @Override + public void run() { + if (isDetached()) { + return; + } + setViewList(views); + getJsonApi().invokeRefreshLogic(null, true, null, null, getStepName(), false); + if (getDialogView() != null) { + addWidgetViews(getDialogView()); + } + } + }); }); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/fragments/JsonWizardFormFragment.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/fragments/JsonWizardFormFragment.java index eedc12321..474b7c72e 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/fragments/JsonWizardFormFragment.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/fragments/JsonWizardFormFragment.java @@ -3,8 +3,6 @@ import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.Toolbar; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; @@ -17,6 +15,9 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; + import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.activities.JsonFormActivity; import com.vijay.jsonwizard.constants.JsonFormConstants; @@ -286,11 +287,11 @@ public void onClick(View view) { getJsonApi().setPreviousPressed(false); Object nextStateTag = view.getTag(R.id.NEXT_STATE); if (nextStateTag == null) { - new NextProgressDialogTask(getJsonFormFragment()).execute(); + new NextProgressDialogTask(getJsonFormFragment()).init(); } else { boolean next = (boolean) nextStateTag; if (next) { - new NextProgressDialogTask(getJsonFormFragment()).execute(); + new NextProgressDialogTask(getJsonFormFragment()).init(); } else { save(); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/interactors/JsonFormInteractor.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/interactors/JsonFormInteractor.java index 61511526a..8fdb641be 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/interactors/JsonFormInteractor.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/interactors/JsonFormInteractor.java @@ -3,9 +3,10 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; -import androidx.annotation.Nullable; import android.view.View; +import androidx.annotation.Nullable; + import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.fragments.JsonFormFragment; @@ -279,7 +280,7 @@ public final Set getDefaultTranslatableStepFields() { } public void cleanUp() { - if(map.get(JsonFormConstants.NATIVE_RADIO_BUTTON) != null){ + if (map.get(JsonFormConstants.NATIVE_RADIO_BUTTON) != null) { NativeRadioButtonFactory nativeRadioButtonFactory = (NativeRadioButtonFactory) map.get(JsonFormConstants.NATIVE_RADIO_BUTTON); nativeRadioButtonFactory.cleanUp(); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/listeners/ExpansionPanelRecordButtonClickListener.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/listeners/ExpansionPanelRecordButtonClickListener.java index 6cab6cff7..7ebbf51af 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/listeners/ExpansionPanelRecordButtonClickListener.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/listeners/ExpansionPanelRecordButtonClickListener.java @@ -43,7 +43,7 @@ public void onClick(View view) { } protected void initiateTask(View view) { - new ExpansionPanelGenericPopupDialogTask(view).execute(); + new ExpansionPanelGenericPopupDialogTask(view).init(); } /** diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenter.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenter.java index 2631ff7a9..ce809d1c0 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenter.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenter.java @@ -536,18 +536,21 @@ public void validateAndWriteValues() { * Check if alarm is ringing and stop it if so */ public void checkAndStopCountdownAlarm() { - try { - JSONObject formJSONObject = new JSONObject(formFragment.getCurrentJsonState()); - JSONArray fields = FormUtils.fields(formJSONObject, mStepName); - for (int i = 0; i < fields.length(); i++) { - JSONObject fieldObject = (JSONObject) fields.get(i); - if (fieldObject.has(JsonFormConstants.COUNTDOWN_TIME_VALUE)) { - CountDownTimerFactory.stopAlarm(); + formFragment.getJsonApi().getAppExecutors().diskIO().execute(()->{ + try { + JSONObject formJSONObject = new JSONObject(formFragment.getCurrentJsonState()); + JSONArray fields = FormUtils.fields(formJSONObject, mStepName); + for (int i = 0; i < fields.length(); i++) { + JSONObject fieldObject = (JSONObject) fields.get(i); + if (fieldObject.has(JsonFormConstants.COUNTDOWN_TIME_VALUE)) { + CountDownTimerFactory.stopAlarm(); + } } + } catch (Exception e) { + Timber.e(e, "Countdown alarm could not be stopped!"); } - } catch (Exception e) { - Timber.e(e, "Countdown alarm could not be stopped!"); - } + }); + } public boolean validateOnSubmit() { @@ -846,7 +849,7 @@ protected void nativeRadioButtonClickActions(View view) { .equals(JsonFormConstants.DATE_PICKER)) { NativeRadioButtonFactory.showDateDialog(view); } else if (JsonFormConstants.CONTENT_INFO.equals(type) && !specifyWidget.equals(JsonFormConstants.DATE_PICKER)) { - new ExpansionPanelGenericPopupDialogTask(view).execute(); + new ExpansionPanelGenericPopupDialogTask(view).init(); } else if (view.getId() == R.id.label_edit_button) { setRadioViewsEditable(view); } else { @@ -1080,8 +1083,7 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { getView().writeValue(mStepName, parentKey, JsonFormConstants.OPTIONS_FIELD_NAME, childKey, String.valueOf(compoundButton.isChecked()), openMrsEntityParent, openMrsEntity, openMrsEntityId, popup); - } else if ( - (compoundButton instanceof AppCompatRadioButton || compoundButton instanceof RadioButton) + } else if ((compoundButton instanceof AppCompatRadioButton || compoundButton instanceof RadioButton) && isChecked) { String parentKey = (String) compoundButton.getTag(R.id.key); String openMrsEntityParent = (String) compoundButton.getTag(R.id.openmrs_entity_parent); @@ -1268,9 +1270,9 @@ private void addRules(JSONObject jsonObject, Set ruleFiles) { } } - public void cleanUp() { cleanupAndExit = true; mJsonFormInteractor.cleanUp(); } + } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineDateUtil.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineDateUtil.java index 9d0267aa4..e5e273063 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineDateUtil.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineDateUtil.java @@ -7,6 +7,7 @@ import com.vijay.jsonwizard.utils.FormUtils; import com.vijay.jsonwizard.utils.Utils; +import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; @@ -23,6 +24,12 @@ */ public class RulesEngineDateUtil { + public static int getAgeFromDate(String dateOfBirth) { + Date date = Utils.getDateFromString(dateOfBirth); + Years age = Years.yearsBetween(new DateTime(date).toLocalDate(), LocalDate.now()); + return age.getYears(); + } + public long getDifferenceDays(String dateString) { Date date = Utils.getDateFromString(dateString); @@ -68,7 +75,7 @@ public String getDateTimeToday() { * @return String */ public String getDuration(String date, String endDate) { - return Utils.getDuration(Utils.getDateFormattedForCalculation(date, Form.getDatePickerDisplayFormat()), + return Utils.getDuration(Utils.getDateFormattedForCalculation(date, Form.getDatePickerDisplayFormat()), endDate); } @@ -80,7 +87,7 @@ public String getWeeksAndDaysFromDays(Integer days) { } public String formatDate(String dateString, String duration) { - LocalDate date = new LocalDate(Utils.reverseDateString(Utils.getDateFormattedForCalculation(dateString, Form.getDatePickerDisplayFormat()), "-")); + LocalDate date = new LocalDate(Utils.reverseDateString(Utils.getDateFormattedForCalculation(dateString, Form.getDatePickerDisplayFormat()), "-")); int result = 0; String cleanDuration = duration.trim().toLowerCase(); @@ -130,7 +137,7 @@ public String addDuration(String durationString) { * @return String with date */ public String addDuration(String dateString, String durationString) { - LocalDate date = new LocalDate(Utils.reverseDateString(Utils.getDateFormattedForCalculation(dateString, Form.getDatePickerDisplayFormat()), "-")); + LocalDate date = new LocalDate(Utils.reverseDateString(Utils.getDateFormattedForCalculation(dateString, Form.getDatePickerDisplayFormat()), "-")); String[] durationArr = getDurationArray(durationString); for (String duration : durationArr) { diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineHelper.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineHelper.java index 4a0ac144a..91deb388d 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineHelper.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/rules/RulesEngineHelper.java @@ -9,12 +9,16 @@ */ public class RulesEngineHelper { - private RulesEngineDateUtil rulesEngineDateUtil = new RulesEngineDateUtil(); + private final RulesEngineDateUtil rulesEngineDateUtil = new RulesEngineDateUtil(); public long getDifferenceDays(String dateString) { return rulesEngineDateUtil.getDifferenceDays(dateString); } + public int getMothersAge(String dateOfBirth) { + return RulesEngineDateUtil.getAgeFromDate(dateOfBirth); + } + public long getDifferenceDays(String dateString, String dateString2) { return rulesEngineDateUtil.getDifferenceDays(dateString, dateString2); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/AttachRepeatingGroupTask.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/AttachRepeatingGroupTask.java index 3b8abeb47..9b1210d64 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/AttachRepeatingGroupTask.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/AttachRepeatingGroupTask.java @@ -1,8 +1,19 @@ package com.vijay.jsonwizard.task; +import static com.vijay.jsonwizard.constants.JsonFormConstants.CALCULATION; +import static com.vijay.jsonwizard.constants.JsonFormConstants.FIELDS; +import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY; +import static com.vijay.jsonwizard.constants.JsonFormConstants.RELEVANCE; +import static com.vijay.jsonwizard.constants.JsonFormConstants.STEPNAME; +import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP_TITLE; +import static com.vijay.jsonwizard.constants.JsonFormConstants.TYPE; +import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; +import static com.vijay.jsonwizard.constants.JsonFormConstants.V_RELATIVE_MAX; +import static com.vijay.jsonwizard.utils.Utils.hideProgressDialog; +import static com.vijay.jsonwizard.utils.Utils.showProgressDialog; + import android.content.Context; import android.graphics.Typeface; -import android.os.AsyncTask; import android.text.SpannableString; import android.text.style.StyleSpan; import android.view.View; @@ -20,6 +31,7 @@ import com.vijay.jsonwizard.fragments.JsonFormFragment; import com.vijay.jsonwizard.interfaces.FormWidgetFactory; import com.vijay.jsonwizard.interfaces.JsonApi; +import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.utils.Utils; import com.vijay.jsonwizard.utils.ValidationStatus; @@ -38,19 +50,7 @@ import timber.log.Timber; -import static com.vijay.jsonwizard.constants.JsonFormConstants.CALCULATION; -import static com.vijay.jsonwizard.constants.JsonFormConstants.FIELDS; -import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY; -import static com.vijay.jsonwizard.constants.JsonFormConstants.RELEVANCE; -import static com.vijay.jsonwizard.constants.JsonFormConstants.STEPNAME; -import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP_TITLE; -import static com.vijay.jsonwizard.constants.JsonFormConstants.TYPE; -import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; -import static com.vijay.jsonwizard.constants.JsonFormConstants.V_RELATIVE_MAX; -import static com.vijay.jsonwizard.utils.Utils.hideProgressDialog; -import static com.vijay.jsonwizard.utils.Utils.showProgressDialog; - -public class AttachRepeatingGroupTask extends AsyncTask> { +public class AttachRepeatingGroupTask { protected final int REPEATING_GROUP_LABEL_TEXT_COLOR = R.color.black; private final ViewParent parent; @@ -64,6 +64,7 @@ public class AttachRepeatingGroupTask extends AsyncTask> private Map>> rulesFileMap = new HashMap<>(); private Map repeatingGroupLayouts; private int currNumRepeatingGroups; + private final AppExecutors appExecutors; public AttachRepeatingGroupTask(final ViewParent parent, int numRepeatingGroups, Map repeatingGroupLayouts, WidgetArgs widgetArgs, ImageButton doneButton) { this.rootLayout = (LinearLayout) parent; @@ -73,28 +74,34 @@ public AttachRepeatingGroupTask(final ViewParent parent, int numRepeatingGroups, this.doneButton = doneButton; this.repeatingGroupLayouts = repeatingGroupLayouts; currNumRepeatingGroups = ((ViewGroup) parent).getChildCount() - 1; + appExecutors = new AppExecutors(); + } + + public void init() { + appExecutors.mainThread().execute(this::onPreExecute); + appExecutors.diskIO().execute(() -> { + this.updateRepeatingGrpInBackground(); + appExecutors.mainThread().execute(this::onPostExecute); + }); + onCancelled(); + } - @Override + protected void onPreExecute() { showProgressDialog(R.string.please_wait_title, R.string.creating_repeating_group_message, widgetArgs.getFormFragment().getContext()); } - @Override - protected List doInBackground(Void... voids) { + protected List updateRepeatingGrpInBackground() { diff = numRepeatingGroups - currNumRepeatingGroups; for (int i = 0; i < diff; i++) { try { - repeatingGroups.add(buildRepeatingGroupLayout(parent)); - } catch (Exception e) { Timber.e(e); } } - updateRepeatingGrpCountObject(); - return repeatingGroups; } @@ -109,11 +116,9 @@ private void updateRepeatingGrpCountObject() { } } - @Override - protected void onPostExecute(List result) { + protected void onPostExecute() { if (diff < 0) { try { - JSONObject step = ((JsonApi) widgetArgs.getContext()).getmJSONObject().getJSONObject(widgetArgs.getStepName()); JSONArray fields = step.getJSONArray(FIELDS); int currNumRepeatingGroups = rootLayout.getChildCount() - 1; @@ -165,18 +170,15 @@ protected void onPostExecute(List result) { hideProgressDialog(); doneButton.setImageResource(R.drawable.ic_done_green); - //for validation validationCleanUp(); } private void validationCleanUp() { doneButton.setTag(R.id.is_repeating_group_generated, true); - LinearLayout referenceLayout = (LinearLayout) ((LinearLayout) parent).getChildAt(0); MaterialEditText materialEditText = (MaterialEditText) referenceLayout.getChildAt(0); materialEditText.setError(null); - Map validationStatusMap = widgetArgs.getFormFragment().getJsonApi().getInvalidFields(); if (validationStatusMap != null) { String fieldKey = Utils.getFieldKeyPrefix(widgetArgs.getStepName(), widgetArgs.getFormFragment().getPresenter().getStepTitle()) + JsonFormConstants.REFERENCE_EDIT_TEXT; @@ -186,20 +188,16 @@ private void validationCleanUp() { private LinearLayout buildRepeatingGroupLayout(final ViewParent parent) throws Exception { Context context = widgetArgs.getContext(); - LinearLayout repeatingGroup = new LinearLayout(context); repeatingGroup.setLayoutParams(WIDTH_MATCH_PARENT_HEIGHT_WRAP_CONTENT); repeatingGroup.setOrientation(LinearLayout.VERTICAL); - LinearLayout rootLayout = (LinearLayout) ((LinearLayout) parent).getChildAt(0); EditText referenceEditText = (EditText) rootLayout.getChildAt(0); TextView repeatingGroupLabel = new TextView(context); if (widgetArgs.getJsonObject().optBoolean(JsonFormConstants.RepeatingGroupFactory.SHOW_GROUP_LABEL, true)) { formatRepeatingGroupLabelText(referenceEditText, repeatingGroupLabel, context); } - repeatingGroup.addView(repeatingGroupLabel); - JSONArray repeatingGroupJson = new JSONArray(repeatingGroupLayouts.get(((LinearLayout) parent).getId())); String groupUniqueId = UUID.randomUUID().toString().replace("-", ""); for (int i = 0; i < repeatingGroupJson.length(); i++) { @@ -255,7 +253,6 @@ protected void addUniqueIdentifiers(JSONObject element, String uniqueId) throws } } - @Override protected void onCancelled() { hideProgressDialog(); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/ExpansionPanelGenericPopupDialogTask.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/ExpansionPanelGenericPopupDialogTask.java index 9c833afe3..ecca0b92b 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/ExpansionPanelGenericPopupDialogTask.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/ExpansionPanelGenericPopupDialogTask.java @@ -13,6 +13,7 @@ import com.vijay.jsonwizard.customviews.ExpansionPanelGenericPopupDialog; import com.vijay.jsonwizard.fragments.JsonFormFragment; import com.vijay.jsonwizard.interfaces.CommonListener; +import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.utils.FormUtils; import com.vijay.jsonwizard.utils.Utils; import com.vijay.jsonwizard.views.CustomTextView; @@ -24,7 +25,7 @@ /** * The {@link AsyncTask} to start and set the required variables on the {@link ExpansionPanelGenericPopupDialog} */ -public class ExpansionPanelGenericPopupDialogTask extends AsyncTask { +public class ExpansionPanelGenericPopupDialogTask { private FormUtils formUtils = new FormUtils(); private Utils utils = new Utils(); private View view; @@ -32,17 +33,20 @@ public class ExpansionPanelGenericPopupDialogTask extends AsyncTask { + progressBar = new ProgressDialog(multiSelectListFactory.getContext()); + progressBar.setMessage(multiSelectListFactory.getContext().getString(R.string.loading_multi_select_list)); + progressBar.show(); }); init(); } private void init() { - appExecutors.diskIO().execute(new Runnable() { - @Override - public void run() { - String source = jsonObject.optString(JsonFormConstants.MultiSelectUtils.SOURCE); - final List multiSelectItems = multiSelectListFactory.loadListItems(source); - if (multiSelectItems == null) { - return; - } - String strGroupingsArray = jsonObject.optString(JsonFormConstants.MultiSelectUtils.GROUPINGS); - boolean sort = jsonObject.optBoolean(JsonFormConstants.MultiSelectUtils.SORT); + appExecutors.diskIO().execute(() -> { + String source = jsonObject.optString(JsonFormConstants.MultiSelectUtils.SOURCE); + final List multiSelectItems = multiSelectListFactory.loadListItems(source); + if (multiSelectItems == null) { + return; + } + String strGroupingsArray = jsonObject.optString(JsonFormConstants.MultiSelectUtils.GROUPINGS); + boolean sort = jsonObject.optBoolean(JsonFormConstants.MultiSelectUtils.SORT); - if (!StringUtils.isBlank(strGroupingsArray) && sort) {//no grouping without sorting - JSONArray jsonArray = null; - try { - jsonArray = new JSONArray(strGroupingsArray); - } catch (JSONException e) { - Timber.e(e); - } - MultiSelectListUtils.addGroupings(multiSelectItems, jsonArray); + if (!StringUtils.isBlank(strGroupingsArray) && sort) {//no grouping without sorting + JSONArray jsonArray = null; + try { + jsonArray = new JSONArray(strGroupingsArray); + } catch (JSONException e) { + Timber.e(e); } - if (sort) { - String sortClass = jsonObject.optString(JsonFormConstants.MultiSelectUtils.SORTING_CLASS); - if (StringUtils.isBlank(sortClass)) { - sortClass = JsonFormConstants.MultiSelectUtils.ALPHABET_SORTING; - } - try { - Class aClass = Class.forName(sortClass); - Collections.sort(multiSelectItems, (Comparator) aClass.newInstance()); - } catch (IllegalAccessException e) { - Timber.e(e); - } catch (InstantiationException e) { - Timber.e(e); - } catch (ClassNotFoundException e) { - Timber.e(e); - } + MultiSelectListUtils.addGroupings(multiSelectItems, jsonArray); + } + if (sort) { + String sortClass = jsonObject.optString(JsonFormConstants.MultiSelectUtils.SORTING_CLASS); + if (StringUtils.isBlank(sortClass)) { + sortClass = JsonFormConstants.MultiSelectUtils.ALPHABET_SORTING; + } + try { + Class aClass = Class.forName(sortClass); + Collections.sort(multiSelectItems, (Comparator) aClass.newInstance()); + } catch (IllegalAccessException e) { + Timber.e(e); + } catch (InstantiationException e) { + Timber.e(e); + } catch (ClassNotFoundException e) { + Timber.e(e); } - - appExecutors.mainThread().execute(new Runnable() { - @Override - public void run() { - onPostExecute(multiSelectItems); - } - }); } + + appExecutors.mainThread().execute(() -> onPostExecute(multiSelectItems)); }); } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/NextProgressDialogTask.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/NextProgressDialogTask.java index 76b4e18e7..477c5c212 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/NextProgressDialogTask.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/task/NextProgressDialogTask.java @@ -2,14 +2,15 @@ import android.app.ProgressDialog; import android.content.Context; -import android.os.AsyncTask; import com.vijay.jsonwizard.fragments.JsonWizardFormFragment; +import com.vijay.jsonwizard.utils.AppExecutors; -public class NextProgressDialogTask extends AsyncTask { +public class NextProgressDialogTask { private JsonWizardFormFragment formFragment; private Context context; private ProgressDialog progressDialog; + private AppExecutors appExecutors; private void showDialog() { setProgressDialog(new ProgressDialog(getContext())); @@ -32,22 +33,13 @@ public NextProgressDialogTask(JsonWizardFormFragment jsonFormFragment) { } } - @Override - protected Void doInBackground(Void... voids) { - getFormFragment().next(); - return null; - } - - @Override - protected void onPreExecute() { - super.onPreExecute(); - showDialog(); - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - hideDialog(); + public void init() { + appExecutors = getFormFragment().getJsonApi().getAppExecutors(); + appExecutors.mainThread().execute(this::showDialog); + appExecutors.diskIO().execute(() -> { + getFormFragment().next(); + appExecutors.mainThread().execute(this::hideDialog); + }); } public JsonWizardFormFragment getFormFragment() { diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/FormUtils.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/FormUtils.java index 44b20e9d9..fc07e7472 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/FormUtils.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/FormUtils.java @@ -1,5 +1,9 @@ package com.vijay.jsonwizard.utils; +import static com.vijay.jsonwizard.utils.Utils.convertStreamToString; +import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonArray; + +import android.annotation.SuppressLint; import android.app.Activity; import android.app.FragmentTransaction; import android.content.Context; @@ -47,7 +51,6 @@ import com.vijay.jsonwizard.rules.RuleConstant; import com.vijay.jsonwizard.views.CustomTextView; -import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import org.jeasy.rules.api.Facts; import org.jetbrains.annotations.NotNull; @@ -63,6 +66,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -78,9 +82,6 @@ import timber.log.Timber; -import static com.vijay.jsonwizard.utils.Utils.convertStreamToString; -import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonArray; - /** * Created by vijay on 24-05-2015. */ @@ -101,7 +102,7 @@ public class FormUtils { private static final String TODAY_JAVAROSA_PROPERTY = "today"; private static final String DEFAULT_FORM_IMAGES_FOLDER = "image/"; private static final String TAG = FormUtils.class.getSimpleName(); - private Utils utils = new Utils(); + private final Utils utils = new Utils(); private GenericDialogInterface genericDialogInterface; public static Point getViewLocationOnScreen(View view) { @@ -299,61 +300,14 @@ public static void updateEndProperties(PropertyManager propertyManager, JSONObje } } - public static JSONObject createOptiBPDataObject(String clientId, String clientOpenSRPId) throws JSONException{ + + public static JSONObject createOptiBPDataObject(String clientId, String clientOpenSRPId) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(JsonFormConstants.OptibpConstants.OPTIBP_KEY_CLIENT_ID, clientId); jsonObject.put(JsonFormConstants.OptibpConstants.OPTIBP_KEY_CLIENT_OPENSRP_ID, clientOpenSRPId); return jsonObject; } - public Map createRadioButtonAndCheckBoxLabel(String stepName, LinearLayout linearLayout, - JSONObject jsonObject, Context context, - JSONArray canvasIds, final Boolean readOnly, - CommonListener listener, boolean popup) throws JSONException { - Map createdViewsMap = new HashMap<>(); - String label = jsonObject.optString(JsonFormConstants.LABEL, ""); - if (StringUtils.isNotBlank(label)) { - String asterisks = ""; - final int labelTextSize = FormUtils.getValueFromSpOrDpOrPx(jsonObject.optString(JsonFormConstants.LABEL_TEXT_SIZE, String.valueOf(context - .getResources().getDimension(R.dimen.default_label_text_size))), context); - String labelTextColor = jsonObject.optString(JsonFormConstants.LABEL_TEXT_COLOR, JsonFormConstants.DEFAULT_TEXT_COLOR); - JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_REQUIRED); - final ConstraintLayout labelConstraintLayout = createLabelLinearLayout(stepName, canvasIds, jsonObject, context, listener); - labelConstraintLayout.setTag(R.id.extraPopup, popup); - final CustomTextView labelText = labelConstraintLayout.findViewById(R.id.label_text); - ImageView editButton = labelConstraintLayout.findViewById(R.id.label_edit_button); - if (requiredObject != null) { - String requiredValue = requiredObject.getString(JsonFormConstants.VALUE); - if (StringUtils.isNotBlank(requiredValue) && (Boolean.TRUE.toString().equalsIgnoreCase(requiredValue) || Boolean.parseBoolean(requiredValue))) { - asterisks = " *"; - } - } - - final String combinedLabelText = "" + label + "" + asterisks; - - //Applying textStyle to the text; - final String textStyle = jsonObject.optString(JsonFormConstants.TEXT_STYLE, JsonFormConstants.NORMAL); - if (labelText != null && editButton != null) { - ((Activity) context).runOnUiThread(new Runnable() { - @Override - public void run() { - setTextStyle(textStyle, labelText); - labelText.setText(Html.fromHtml(combinedLabelText)); - labelText.setTextSize(labelTextSize); - labelConstraintLayout.setEnabled(!readOnly); - } - }); - labelText.setTag(R.id.extraPopup, popup); - labelText.setTag(R.id.original_text, Html.fromHtml(combinedLabelText)); - canvasIds.put(labelConstraintLayout.getId()); - linearLayout.addView(labelConstraintLayout); - createdViewsMap.put(JsonFormConstants.EDIT_BUTTON, editButton); - createdViewsMap.put(JsonFormConstants.CUSTOM_TEXT, labelText); - } - } - return createdViewsMap; - } - public static int getValueFromSpOrDpOrPx(String spOrDpOrPx, Context context) { int px = 0; if (!TextUtils.isEmpty(spOrDpOrPx)) { @@ -373,63 +327,6 @@ public static int getValueFromSpOrDpOrPx(String spOrDpOrPx, Context context) { return px; } - public ConstraintLayout createLabelLinearLayout(String stepName, JSONArray canvasIds, - JSONObject jsonObject, - Context context, - CommonListener listener) throws JSONException { - String openMrsEntityParent = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY_PARENT, null); - String openMrsEntity = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY, null); - String openMrsEntityId = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY_ID, null); - String relevance = jsonObject.optString(JsonFormConstants.RELEVANCE); - String calculation = jsonObject.optString(JsonFormConstants.CALCULATION); - String constraints = jsonObject.optString(JsonFormConstants.CONSTRAINTS); - - ConstraintLayout constraintLayout = getConstraintLayout(stepName, canvasIds, jsonObject, context, openMrsEntityParent, openMrsEntity, openMrsEntityId); - attachRefreshLogic(context, relevance, calculation, constraints, constraintLayout); - - ImageView imageView = constraintLayout.findViewById(R.id.label_info); - showInfoIcon(stepName, jsonObject, listener, FormUtils.getInfoDialogAttributes(jsonObject), imageView, canvasIds); - - return constraintLayout; - } - - private void attachRefreshLogic(Context context, String relevance, String calculation, String constraints, ConstraintLayout constraintLayout) { - if (!TextUtils.isEmpty(relevance) && context instanceof JsonApi) { - constraintLayout.setTag(R.id.relevance, relevance); - ((JsonApi) context).addSkipLogicView(constraintLayout); - } - - if (!TextUtils.isEmpty(calculation) && context instanceof JsonApi) { - constraintLayout.setTag(R.id.calculation, calculation); - ((JsonApi) context).addCalculationLogicView(constraintLayout); - } - - if (!TextUtils.isEmpty(constraints) && context instanceof JsonApi) { - constraintLayout.setTag(R.id.constraints, constraints); - ((JsonApi) context).addCalculationLogicView(constraintLayout); - } - } - - @NotNull - public ConstraintLayout getConstraintLayout(String stepName, JSONArray canvasIds, JSONObject jsonObject, Context context, String openMrsEntityParent, String openMrsEntity, String openMrsEntityId) throws JSONException { - ConstraintLayout constraintLayout = getRootConstraintLayout(context); - constraintLayout.setId(ViewUtil.generateViewId()); - canvasIds.put(constraintLayout.getId()); - constraintLayout.setTag(R.id.canvas_ids, canvasIds.toString()); - constraintLayout.setTag(R.id.key, jsonObject.getString(JsonFormConstants.KEY)); - constraintLayout.setTag(R.id.type, jsonObject.getString(JsonFormConstants.TYPE)); - constraintLayout.setTag(R.id.openmrs_entity_parent, openMrsEntityParent); - constraintLayout.setTag(R.id.openmrs_entity, openMrsEntity); - constraintLayout.setTag(R.id.openmrs_entity_id, openMrsEntityId); - constraintLayout.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY)); - constraintLayout.setId(ViewUtil.generateViewId()); - return constraintLayout; - } - - public ConstraintLayout getRootConstraintLayout(Context context) { - return (ConstraintLayout) LayoutInflater.from(context).inflate(R.layout.native_form_labels, null); - } - /** * */ @@ -462,44 +359,6 @@ public static int dpToPixels(Context context, float dps) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dps, context.getResources().getDisplayMetrics()); } - public void showInfoIcon(String stepName, JSONObject jsonObject, CommonListener listener, - @NonNull HashMap imageAttributes, ImageView imageView, JSONArray canvasIds) - throws JSONException { - if (imageView != null) { - //Display custom dialog if has image is true otherwise normal alert dialog is enough - if (imageAttributes.get(JsonFormConstants.LABEL_INFO_HAS_IMAGE) != null && - Boolean.parseBoolean(imageAttributes.get(JsonFormConstants.LABEL_INFO_HAS_IMAGE))) { - - imageView.setTag(R.id.label_dialog_image_src, - imageAttributes.get(JsonFormConstants.LABEL_INFO_IMAGE_SRC)); - imageView.setVisibility(View.VISIBLE); - - } - - if (imageAttributes.get(JsonFormConstants.LABEL_INFO_TEXT) != null) { - - imageView - .setTag(R.id.label_dialog_info, imageAttributes.get(JsonFormConstants.LABEL_INFO_TEXT)); - imageView - .setTag(R.id.label_dialog_title, imageAttributes.get(JsonFormConstants.LABEL_INFO_TITLE)); - imageView.setVisibility(View.VISIBLE); - - } - - if (imageAttributes.get(JsonFormConstants.LABEL_IS_DYNAMIC) != null) { - imageView.setTag(R.id.dynamic_label_info, jsonObject.getJSONArray(JsonFormConstants.DYNAMIC_LABEL_INFO)); - imageView.setTag(R.id.label_dialog_title, imageAttributes.get(JsonFormConstants.LABEL_INFO_TITLE)); - imageView.setVisibility(View.VISIBLE); - } - - imageView.setTag(R.id.key, jsonObject.getString(JsonFormConstants.KEY)); - imageView.setTag(R.id.type, jsonObject.getString(JsonFormConstants.TYPE)); - imageView.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY)); - imageView.setTag(R.id.canvas_ids, canvasIds.toString()); - imageView.setOnClickListener(listener); - } - } - public static HashMap getInfoDialogAttributes(JSONObject jsonObject) { HashMap imageAttributes = new HashMap<>(); imageAttributes.put(JsonFormConstants.LABEL_INFO_TITLE, @@ -634,12 +493,7 @@ public static void setRequiredOnHint(AppCompatEditText editText) { public static void setEditMode(JSONObject jsonObject, View editableView, ImageView editButton) throws JSONException { - if (jsonObject.has(JsonFormConstants.EDITABLE) && jsonObject - .has(JsonFormConstants.READ_ONLY)) { - editButton.setVisibility(View.VISIBLE); - editableView.setEnabled(false); - } - else if (jsonObject.has(JsonFormConstants.EDITABLE)) { + if (jsonObject.has(JsonFormConstants.EDITABLE)) { boolean editable = jsonObject.getBoolean(JsonFormConstants.EDITABLE); if (editable) { editButton.setVisibility(View.VISIBLE); @@ -651,6 +505,10 @@ else if (jsonObject.has(JsonFormConstants.EDITABLE)) { boolean readyOnly = jsonObject.getBoolean(JsonFormConstants.READ_ONLY); editableView.setEnabled(!readyOnly); editButton.setVisibility(View.GONE); + } else if (jsonObject.has(JsonFormConstants.EDITABLE) && jsonObject + .has(JsonFormConstants.READ_ONLY)) { + editButton.setVisibility(View.VISIBLE); + editableView.setEnabled(false); } } @@ -828,13 +686,17 @@ public static JSONArray getCheckboxValueJsonArray(HashSet optionValues) return new JSONArray(optionValues); } - public static HashSet getCurrentCheckboxValues(JSONArray optionsArray) - throws JSONException { - HashSet result = new HashSet<>(); - for (int i = 0; i < optionsArray.length(); i++) { - result.add(optionsArray.getString(i)); + public static HashSet getCurrentCheckboxValues(JSONArray optionsArray) { + try { + HashSet result = new HashSet<>(); + for (int i = 0; i < optionsArray.length(); i++) { + result.add(optionsArray.getString(i)); + } + return result; + } catch (Exception e) { + Timber.e(e); + return null; } - return result; } /** @@ -931,6 +793,162 @@ public static boolean isFieldRequired(JSONObject fieldObject) throws JSONExcepti isValueRequired; } + public static int getClientFormId(@NonNull JSONObject jsonObject) { + try { + return jsonObject.getInt(JsonFormConstants.Properties.CLIENT_FORM_ID); + } catch (JSONException e) { + Timber.e(e); + return 0; + } + } + + public static boolean isFormNew(@NonNull JSONObject jsonObject) { + return jsonObject.optBoolean(JsonFormConstants.Properties.IS_NEW, false); + } + + public Map createRadioButtonAndCheckBoxLabel(String stepName, LinearLayout linearLayout, + JSONObject jsonObject, Context context, + JSONArray canvasIds, final Boolean readOnly, + CommonListener listener, boolean popup) throws JSONException { + Map createdViewsMap = new HashMap<>(); + String label = jsonObject.optString(JsonFormConstants.LABEL, ""); + if (StringUtils.isNotBlank(label)) { + String asterisks = ""; + final int labelTextSize = FormUtils.getValueFromSpOrDpOrPx(jsonObject.optString(JsonFormConstants.LABEL_TEXT_SIZE, String.valueOf(context + .getResources().getDimension(R.dimen.default_label_text_size))), context); + String labelTextColor = jsonObject.optString(JsonFormConstants.LABEL_TEXT_COLOR, JsonFormConstants.DEFAULT_TEXT_COLOR); + JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_REQUIRED); + final ConstraintLayout labelConstraintLayout = createLabelLinearLayout(stepName, canvasIds, jsonObject, context, listener); + labelConstraintLayout.setTag(R.id.extraPopup, popup); + final CustomTextView labelText = labelConstraintLayout.findViewById(R.id.label_text); + ImageView editButton = labelConstraintLayout.findViewById(R.id.label_edit_button); + if (requiredObject != null) { + String requiredValue = requiredObject.getString(JsonFormConstants.VALUE); + if (StringUtils.isNotBlank(requiredValue) && (Boolean.TRUE.toString().equalsIgnoreCase(requiredValue) || Boolean.parseBoolean(requiredValue))) { + asterisks = " *"; + } + } + + final String combinedLabelText = "" + label + "" + asterisks; + + //Applying textStyle to the text; + final String textStyle = jsonObject.optString(JsonFormConstants.TEXT_STYLE, JsonFormConstants.NORMAL); + if (labelText != null && editButton != null) { + ((Activity) context).runOnUiThread(new Runnable() { + @Override + public void run() { + setTextStyle(textStyle, labelText); + labelText.setText(Html.fromHtml(combinedLabelText)); + labelText.setTextSize(labelTextSize); + labelConstraintLayout.setEnabled(!readOnly); + } + }); + labelText.setTag(R.id.extraPopup, popup); + labelText.setTag(R.id.original_text, Html.fromHtml(combinedLabelText)); + canvasIds.put(labelConstraintLayout.getId()); + linearLayout.addView(labelConstraintLayout); + createdViewsMap.put(JsonFormConstants.EDIT_BUTTON, editButton); + createdViewsMap.put(JsonFormConstants.CUSTOM_TEXT, labelText); + } + } + return createdViewsMap; + } + + public ConstraintLayout createLabelLinearLayout(String stepName, JSONArray canvasIds, + JSONObject jsonObject, + Context context, + CommonListener listener) throws JSONException { + String openMrsEntityParent = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY_PARENT, null); + String openMrsEntity = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY, null); + String openMrsEntityId = jsonObject.optString(JsonFormConstants.OPENMRS_ENTITY_ID, null); + String relevance = jsonObject.optString(JsonFormConstants.RELEVANCE); + String calculation = jsonObject.optString(JsonFormConstants.CALCULATION); + String constraints = jsonObject.optString(JsonFormConstants.CONSTRAINTS); + + ConstraintLayout constraintLayout = getConstraintLayout(stepName, canvasIds, jsonObject, context, openMrsEntityParent, openMrsEntity, openMrsEntityId); + attachRefreshLogic(context, relevance, calculation, constraints, constraintLayout); + + ImageView imageView = constraintLayout.findViewById(R.id.label_info); + showInfoIcon(stepName, jsonObject, listener, FormUtils.getInfoDialogAttributes(jsonObject), imageView, canvasIds); + + return constraintLayout; + } + + private void attachRefreshLogic(Context context, String relevance, String calculation, String constraints, ConstraintLayout constraintLayout) { + if (!TextUtils.isEmpty(relevance) && context instanceof JsonApi) { + constraintLayout.setTag(R.id.relevance, relevance); + ((JsonApi) context).addSkipLogicView(constraintLayout); + } + + if (!TextUtils.isEmpty(calculation) && context instanceof JsonApi) { + constraintLayout.setTag(R.id.calculation, calculation); + ((JsonApi) context).addCalculationLogicView(constraintLayout); + } + + if (!TextUtils.isEmpty(constraints) && context instanceof JsonApi) { + constraintLayout.setTag(R.id.constraints, constraints); + ((JsonApi) context).addCalculationLogicView(constraintLayout); + } + } + + @NotNull + public ConstraintLayout getConstraintLayout(String stepName, JSONArray canvasIds, JSONObject jsonObject, Context context, String openMrsEntityParent, String openMrsEntity, String openMrsEntityId) throws JSONException { + ConstraintLayout constraintLayout = getRootConstraintLayout(context); + constraintLayout.setId(ViewUtil.generateViewId()); + canvasIds.put(constraintLayout.getId()); + constraintLayout.setTag(R.id.canvas_ids, canvasIds.toString()); + constraintLayout.setTag(R.id.key, jsonObject.getString(JsonFormConstants.KEY)); + constraintLayout.setTag(R.id.type, jsonObject.getString(JsonFormConstants.TYPE)); + constraintLayout.setTag(R.id.openmrs_entity_parent, openMrsEntityParent); + constraintLayout.setTag(R.id.openmrs_entity, openMrsEntity); + constraintLayout.setTag(R.id.openmrs_entity_id, openMrsEntityId); + constraintLayout.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY)); + constraintLayout.setId(ViewUtil.generateViewId()); + return constraintLayout; + } + + public ConstraintLayout getRootConstraintLayout(Context context) { + return (ConstraintLayout) LayoutInflater.from(context).inflate(R.layout.native_form_labels, null); + } + + public void showInfoIcon(String stepName, JSONObject jsonObject, CommonListener listener, + @NonNull HashMap imageAttributes, ImageView imageView, JSONArray canvasIds) + throws JSONException { + if (imageView != null) { + //Display custom dialog if has image is true otherwise normal alert dialog is enough + if (imageAttributes.get(JsonFormConstants.LABEL_INFO_HAS_IMAGE) != null && + Boolean.parseBoolean(imageAttributes.get(JsonFormConstants.LABEL_INFO_HAS_IMAGE))) { + + imageView.setTag(R.id.label_dialog_image_src, + imageAttributes.get(JsonFormConstants.LABEL_INFO_IMAGE_SRC)); + imageView.setVisibility(View.VISIBLE); + + } + + if (imageAttributes.get(JsonFormConstants.LABEL_INFO_TEXT) != null) { + + imageView + .setTag(R.id.label_dialog_info, imageAttributes.get(JsonFormConstants.LABEL_INFO_TEXT)); + imageView + .setTag(R.id.label_dialog_title, imageAttributes.get(JsonFormConstants.LABEL_INFO_TITLE)); + imageView.setVisibility(View.VISIBLE); + + } + + if (imageAttributes.get(JsonFormConstants.LABEL_IS_DYNAMIC) != null) { + imageView.setTag(R.id.dynamic_label_info, jsonObject.getJSONArray(JsonFormConstants.DYNAMIC_LABEL_INFO)); + imageView.setTag(R.id.label_dialog_title, imageAttributes.get(JsonFormConstants.LABEL_INFO_TITLE)); + imageView.setVisibility(View.VISIBLE); + } + + imageView.setTag(R.id.key, jsonObject.getString(JsonFormConstants.KEY)); + imageView.setTag(R.id.type, jsonObject.getString(JsonFormConstants.TYPE)); + imageView.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY)); + imageView.setTag(R.id.canvas_ids, canvasIds.toString()); + imageView.setOnClickListener(listener); + } + } + public void showGenericDialog(View view) { Context context = (Context) view.getTag(R.id.specify_context); String specifyContent = (String) view.getTag(R.id.specify_content); @@ -1307,6 +1325,21 @@ public Facts getCheckBoxResults(JSONObject jsonObject) throws JSONException { return result; } + public JSONObject getOptionFromOptionsUsingKey(JSONArray options, String key) throws JSONException { + JSONObject option = new JSONObject(); + if (options != null && options.length() > 0) { + for (int i = 0; i < options.length(); i++) { + JSONObject checkOption = options.getJSONObject(i); + if (checkOption != null && checkOption.has(JsonFormConstants.KEY) && checkOption.getString(JsonFormConstants.KEY).equals(key)) { + option = checkOption; + break; + } + } + } + + return option; + } + /** * @param multiRelevance {@link Boolean} * @param object {@link JSONObject} @@ -1319,7 +1352,7 @@ public Facts getRadioButtonResults(Boolean multiRelevance, JSONObject object) th JSONArray jsonArray = object.getJSONArray(JsonFormConstants.OPTIONS_FIELD_NAME); for (int j = 0; j < jsonArray.length(); j++) { if (object.has(JsonFormConstants.VALUE)) { - if (object.getString(JsonFormConstants.VALUE).equals(jsonArray.getJSONObject(j).getString(JsonFormConstants.KEY))) { + if (Utils.returnValue(object).equals(jsonArray.getJSONObject(j).getString(JsonFormConstants.KEY))) { result.put(jsonArray.getJSONObject(j).getString(JsonFormConstants.KEY), String.valueOf(true)); } else { if (!object.has(RuleConstant.IS_RULE_CHECK) || !object.getBoolean(RuleConstant.IS_RULE_CHECK)) { @@ -1337,14 +1370,28 @@ public Facts getRadioButtonResults(Boolean multiRelevance, JSONObject object) th return result; } + @SuppressLint("NewApi") public void updateValueToJSONArray(JSONObject jsonObject, String valueString) { + NativeFormsProperties nativeFormsProperties = JsonFormFragment.getNativeFormProperties(); try { - JSONArray values = null; + JSONArray values; if (StringUtils.isNotEmpty(valueString)) { - values = new JSONArray(valueString); - } - if (values != null) { - jsonObject.put(JsonFormConstants.VALUE, values); + if (nativeFormsProperties != null && nativeFormsProperties.isTrue(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)) { + if (valueString.charAt(0) == '{') { + JSONObject object = new JSONObject(valueString); + values = new JSONArray(object.optString(JsonFormConstants.TEXT, "")); + } else { + JSONObject createJsonValues = Utils.generateTranslatableValue(jsonObject.optString(JsonFormConstants.VALUE, ""), jsonObject); + values = new JSONArray(createJsonValues); + } + } else { + values = new JSONArray(valueString); + } + if (values != null) { + //added + jsonObject.put(JsonFormConstants.VALUE, values); + + } } } catch (JSONException e) { Timber.e(e, "%s --> updateValueToJSONArray", this.getClass().getCanonicalName()); @@ -1521,7 +1568,7 @@ public void getOptionsOpenMRSAttributes(JSONObject item, JSONArray valueOpenMRSA if ((JsonFormConstants.NATIVE_RADIO_BUTTON.equals(item.getString(JsonFormConstants.TYPE)) || JsonFormConstants.EXTENDED_RADIO_BUTTON.equals(item.getString(JsonFormConstants.TYPE))) && item.has(JsonFormConstants.VALUE)) { - String value = item.optString(JsonFormConstants.VALUE); + String value = Utils.extractValueFromJson(item.optString(JsonFormConstants.VALUE)); if (itemOption.has(JsonFormConstants.KEY) && value.equals(itemOption.getString(JsonFormConstants.KEY))) { extractOptionOpenMRSAttributes(valueOpenMRSAttributes, itemOption, item.getString(JsonFormConstants.KEY)); @@ -1541,7 +1588,15 @@ public String getOptionsValueRadioButton(String value, JSONArray options) throws if (!TextUtils.isEmpty(value)) { for (int i = 0; i < options.length(); i++) { JSONObject option = options.getJSONObject(i); - if (option.has(JsonFormConstants.KEY) && value.equals(option.getString(JsonFormConstants.KEY))) { + if (value.charAt(0) == '{') { + JSONObject valueObject = new JSONObject(value); + if (valueObject.getString("value").equals(option.getString(JsonFormConstants.KEY))) { + String key = option.getString(JsonFormConstants.KEY); + String text = option.getString(JsonFormConstants.TEXT); + secondaryValue = key + ":" + text; + break; + } + } else if (option.has(JsonFormConstants.KEY) && value.equals(option.getString(JsonFormConstants.KEY))) { String key = option.getString(JsonFormConstants.KEY); String text = option.getString(JsonFormConstants.TEXT); secondaryValue = key + ":" + text; @@ -1552,7 +1607,8 @@ public String getOptionsValueRadioButton(String value, JSONArray options) throws return secondaryValue; } - public void getSpinnerValueOpenMRSAttributes(JSONObject item, JSONArray valueOpenMRSAttributes) throws JSONException { + public void getSpinnerValueOpenMRSAttributes(JSONObject item, JSONArray + valueOpenMRSAttributes) throws JSONException { if (item == null || !item.getString(JsonFormConstants.TYPE).equals(JsonFormConstants.SPINNER)) { return; @@ -1585,8 +1641,8 @@ public void getSpinnerValueOpenMRSAttributes(JSONObject item, JSONArray valueOpe } } - - private void addOpenMRSAttributes(JSONArray valueOpenMRSAttributes, JSONObject item, String key, String openMRSEntityId) throws JSONException { + private void addOpenMRSAttributes(JSONArray valueOpenMRSAttributes, JSONObject item, String + key, String openMRSEntityId) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(JsonFormConstants.KEY, key); jsonObject.put(JsonFormConstants.OPENMRS_ENTITY_PARENT, item.getString(JsonFormConstants.OPENMRS_ENTITY_PARENT)); @@ -1596,7 +1652,8 @@ private void addOpenMRSAttributes(JSONArray valueOpenMRSAttributes, JSONObject i valueOpenMRSAttributes.put(jsonObject); } - private JSONObject createValueObject(String key, String type, String label, int index, JSONArray values, JSONObject openMRSAttributes, JSONArray valueOpenMRSAttributes) { + private JSONObject createValueObject(String key, String type, String label, + int index, JSONArray values, JSONObject openMRSAttributes, JSONArray valueOpenMRSAttributes) { JSONObject jsonObject = new JSONObject(); try { if (values.length() > 0) { @@ -1625,7 +1682,8 @@ private JSONObject createValueObject(String key, String type, String label, int * @param valueOpenMRSAttributes * @return */ - public JSONObject createSecondaryValueObject(String key, String type, JSONArray values, JSONObject openMRSAttributes, + public JSONObject createSecondaryValueObject(String key, String type, JSONArray + values, JSONObject openMRSAttributes, JSONArray valueOpenMRSAttributes) { JSONObject jsonObject = new JSONObject(); try { @@ -1653,7 +1711,8 @@ public JSONObject createSecondaryValueObject(String key, String type, JSONArray * @param itemKey {@link String} * @throws JSONException */ - protected void extractOptionOpenMRSAttributes(JSONArray valueOpenMRSAttributes, JSONObject itemOption, String itemKey) + protected void extractOptionOpenMRSAttributes(JSONArray valueOpenMRSAttributes, JSONObject + itemOption, String itemKey) throws JSONException { if (itemOption.has(JsonFormConstants.OPENMRS_ENTITY_PARENT) && itemOption.has(JsonFormConstants.OPENMRS_ENTITY) && itemOption.has(JsonFormConstants.OPENMRS_ENTITY_ID)) { @@ -1666,6 +1725,15 @@ protected void extractOptionOpenMRSAttributes(JSONArray valueOpenMRSAttributes, valueOpenMRSObject.put(JsonFormConstants.OPENMRS_ENTITY_PARENT, openmrsEntityParent); valueOpenMRSObject.put(JsonFormConstants.OPENMRS_ENTITY, openmrsEntity); valueOpenMRSObject.put(JsonFormConstants.OPENMRS_ENTITY_ID, openmrsEntityId); + if(itemOption.has(JsonFormConstants.TEXT) && itemOption.has(JsonFormConstants.KEY)) { + valueOpenMRSObject.put(JsonFormConstants.VALUE, itemOption.getString(JsonFormConstants.KEY)); + valueOpenMRSObject.put(JsonFormConstants.TEXT, itemOption.getString(JsonFormConstants.TEXT)); + JSONArray options = new JSONArray(); + options.put(itemOption); + // adds the selected option as an option array to fill the human readable value; + valueOpenMRSObject.put(JsonFormConstants.OPTIONS_FIELD_NAME,options); + } + valueOpenMRSAttributes.put(valueOpenMRSObject); } @@ -1702,7 +1770,8 @@ public JSONArray loadExpansionPanelValues(JSONArray formFields, String parentKey * @param secondaryValues {@link JSONArray} * @return expansionPanelValuesMap {@link Map<>} */ - public Map createSecondaryValuesMap(JSONArray secondaryValues) { + public Map createSecondaryValuesMap(JSONArray + secondaryValues) { Map expansionPanelValuesModelMap = new HashMap<>(); if (secondaryValues != null && secondaryValues.length() > 0) { for (int i = 0; i < secondaryValues.length(); i++) { @@ -1768,7 +1837,8 @@ public JSONArray getValueOpenMRSAttributes(JSONObject jsonObject) throws JSONExc * @param expansionPanelValuesModelMap {@link Map} -- secondary values map * @return fields {@link JSONArray} -- all the sub form fields */ - public JSONArray addExpansionPanelFormValues(JSONArray fields, Map expansionPanelValuesModelMap) { + public JSONArray addExpansionPanelFormValues(JSONArray + fields, Map expansionPanelValuesModelMap) { if (fields != null && expansionPanelValuesModelMap != null) { for (int i = 0; i < fields.length(); i++) { JSONObject formValue; @@ -1847,16 +1917,20 @@ public String setValues(JSONArray jsonArray, String type) { return value.replaceAll(", $", ""); } - public JSONObject getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull String formIdentity) throws JSONException { + @Nullable + public JSONObject getFormJsonFromRepositoryOrAssets(@NonNull Context + context, @NonNull String formIdentity) throws JSONException { ClientFormContract.Dao clientFormRepository = NativeFormLibrary.getInstance().getClientFormDao(); return getFormJsonFromRepositoryOrAssetsWithOptionalCallback(context, clientFormRepository, formIdentity, null); } - public JSONObject getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String formIdentity) throws JSONException { + @Nullable + public JSONObject getFormJsonFromRepositoryOrAssets(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String formIdentity) throws + JSONException { return getFormJsonFromRepositoryOrAssetsWithOptionalCallback(context, clientFormRepository, formIdentity, null); } - /** * Fetches the JSON form from the repository or assets folder and handles the JSONException thrown * by providing the user with rollback capability. The rollback form chosen by the user will be @@ -1866,7 +1940,8 @@ public JSONObject getFormJsonFromRepositoryOrAssets(@NonNull Context context, @N * @param formIdentity * @param onFormFetchedCallback */ - public void getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull String formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { + public void getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull String + formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { ClientFormContract.Dao clientFormRepository = NativeFormLibrary.getInstance().getClientFormDao(); try { getFormJsonFromRepositoryOrAssetsWithOptionalCallback(context, clientFormRepository, formIdentity, onFormFetchedCallback); @@ -1875,8 +1950,9 @@ public void getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull } } - - public void getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String formIdentity, @Nullable OnFormFetchedCallback onFormFetchedCallback) { + public void getFormJsonFromRepositoryOrAssets(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String + formIdentity, @Nullable OnFormFetchedCallback onFormFetchedCallback) { try { getFormJsonFromRepositoryOrAssetsWithOptionalCallback(context, clientFormRepository, formIdentity, onFormFetchedCallback); } catch (JSONException ex) { @@ -1896,7 +1972,10 @@ public void getFormJsonFromRepositoryOrAssets(@NonNull Context context, @NonNull * @return * @throws JSONException */ - private JSONObject getFormJsonFromRepositoryOrAssetsWithOptionalCallback(@NonNull Context context, @Nullable ClientFormContract.Dao clientFormRepository, String formIdentity, @Nullable final OnFormFetchedCallback onFormFetchedCallback) throws JSONException { + private JSONObject getFormJsonFromRepositoryOrAssetsWithOptionalCallback(@NonNull Context + context, @Nullable ClientFormContract.Dao clientFormRepository, String formIdentity, + @Nullable final OnFormFetchedCallback onFormFetchedCallback) throws + JSONException { if (clientFormRepository != null) { ClientFormContract.Model clientForm = getClientFormFromRepository(context, clientFormRepository, formIdentity); @@ -1947,6 +2026,7 @@ public void onFormFetched(@Nullable String form) { } } + @SuppressLint("NewApi") public JSONObject getFormJson(@NonNull Context context, @NonNull String formIdentity) { try { String locale = context.getResources().getConfiguration().locale.getLanguage(); @@ -1962,7 +2042,7 @@ public JSONObject getFormJson(@NonNull Context context, @NonNull String formIden .open("json.form/" + formIdentity + JsonFormConstants.JSON_FILE_EXTENSION); } BufferedReader reader = new BufferedReader( - new InputStreamReader(inputStream, CharEncoding.UTF_8)); + new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String jsonString; StringBuilder stringBuilder = new StringBuilder(); @@ -1970,7 +2050,6 @@ public JSONObject getFormJson(@NonNull Context context, @NonNull String formIden stringBuilder.append(jsonString); } inputStream.close(); - return new JSONObject(stringBuilder.toString()); } catch (IOException | JSONException e) { Timber.e(e); @@ -1978,7 +2057,7 @@ public JSONObject getFormJson(@NonNull Context context, @NonNull String formIden } } - protected String getLocaleFormIdentity(final Context context, final String formIdentity){ + protected String getLocaleFormIdentity(final Context context, final String formIdentity) { String locale = context.getResources().getConfiguration().locale.getLanguage(); if (!Locale.ENGLISH.getLanguage().equals(locale)) { return formIdentity + "-" + locale; @@ -1986,7 +2065,8 @@ protected String getLocaleFormIdentity(final Context context, final String formI return formIdentity; } - private ClientFormContract.Model getClientFormFromRepository(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormRepository, String formIdentity) { + private ClientFormContract.Model getClientFormFromRepository(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormRepository, String formIdentity) { //Check the current locale of the app to load the correct version of the form in the desired language String localeFormIdentity = getLocaleFormIdentity(context, formIdentity); @@ -1999,7 +2079,8 @@ private ClientFormContract.Model getClientFormFromRepository(@NonNull Context co return clientForm; } - public void handleJsonFormOrRulesError(@NonNull Context context, @NonNull String formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { + public void handleJsonFormOrRulesError(@NonNull Context context, @NonNull String + formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { ClientFormContract.Dao clientFormRepository = NativeFormLibrary.getInstance().getClientFormDao(); if (clientFormRepository != null) { handleJsonFormOrRulesError(context, clientFormRepository, false, formIdentity, onFormFetchedCallback); @@ -2008,11 +2089,16 @@ public void handleJsonFormOrRulesError(@NonNull Context context, @NonNull String } } - public void handleJsonFormOrRulesError(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { + public void handleJsonFormOrRulesError(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormRepository, @NonNull String + formIdentity, @NonNull OnFormFetchedCallback onFormFetchedCallback) { handleJsonFormOrRulesError(context, clientFormRepository, false, formIdentity, onFormFetchedCallback); } - public void handleJsonFormOrRulesError(@NonNull final Context context, @NonNull final ClientFormContract.Dao clientFormRepository, final boolean isRulesFile, @NonNull final String formIdentity, @NonNull final OnFormFetchedCallback onFormFetchedCallback) { + public void handleJsonFormOrRulesError(@NonNull final Context context, + @NonNull final ClientFormContract.Dao clientFormRepository, final boolean isRulesFile, + @NonNull final String formIdentity, + @NonNull final OnFormFetchedCallback onFormFetchedCallback) { final ClientFormContract.Model clientForm = getClientFormFromRepository(context, clientFormRepository, formIdentity); List clientForms = clientFormRepository.getClientFormByIdentifier(clientForm.getIdentifier()); @@ -2062,7 +2148,10 @@ public void onCancelClicked() { } } - public JSONObject getSubFormJsonFromRepository(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormDao, String formIdentity, String subFormsLocation, boolean translateSubForm) throws JSONException { + @Nullable + public JSONObject getSubFormJsonFromRepository(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormDao, String formIdentity, String + subFormsLocation, boolean translateSubForm) throws JSONException { //Check the current locale of the app to load the correct version of the form in the desired language String localeFormIdentity = getLocaleFormIdentity(context, formIdentity); @@ -2093,14 +2182,16 @@ public JSONObject getSubFormJsonFromRepository(@NonNull Context context, @NonNul return null; } - public BufferedReader getRulesFromRepository(@NonNull Context context, @NonNull ClientFormContract.Dao clientFormDao, @NonNull String fileName) { + @Nullable + public BufferedReader getRulesFromRepository(@NonNull Context + context, @NonNull ClientFormContract.Dao clientFormDao, @NonNull String fileName) { //Check the current locale of the app to load the correct version of the form in the desired language String localeFormIdentity = getLocaleFormIdentity(context, fileName); ClientFormContract.Model clientForm = clientFormDao.getActiveClientFormByIdentifier(localeFormIdentity); if (clientForm == null && StringUtils.isNotBlank(fileName) && fileName.contains("/") && !fileName.endsWith("/")) { // Strip anything before the '/' - localeFormIdentity = localeFormIdentity.split("/")[1]; + localeFormIdentity = localeFormIdentity.split("/")[1]; //retry with just the filename without the file path prefix clientForm = clientFormDao.getActiveClientFormByIdentifier(localeFormIdentity); @@ -2133,7 +2224,8 @@ protected String extractFormNameWithoutExtension(String localeFormIdentity) { localeFormIdentity + JsonFormConstants.JSON_FILE_EXTENSION; } - public void injectFormStatus(@NonNull JSONObject jsonObject, @NonNull ClientFormContract.Model clientForm) { + public void injectFormStatus(@NonNull JSONObject + jsonObject, @NonNull ClientFormContract.Model clientForm) { if (clientForm.isNew()) { try { jsonObject.put(JsonFormConstants.Properties.IS_NEW, clientForm.isNew()); @@ -2145,17 +2237,4 @@ public void injectFormStatus(@NonNull JSONObject jsonObject, @NonNull ClientForm } } - public static int getClientFormId(@NonNull JSONObject jsonObject) { - try { - return jsonObject.getInt(JsonFormConstants.Properties.CLIENT_FORM_ID); - } catch (JSONException e) { - Timber.e(e); - return 0; - } - } - - public static boolean isFormNew(@NonNull JSONObject jsonObject) { - return jsonObject.optBoolean(JsonFormConstants.Properties.IS_NEW, false); - } - } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormLangUtils.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormLangUtils.java index d9998f282..aba2924ab 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormLangUtils.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormLangUtils.java @@ -1,5 +1,7 @@ package com.vijay.jsonwizard.utils; +import static com.vijay.jsonwizard.constants.JsonFormConstants.MLS.PROPERTIES_FILE_NAME; + import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -22,8 +24,6 @@ import timber.log.Timber; -import static com.vijay.jsonwizard.constants.JsonFormConstants.MLS.PROPERTIES_FILE_NAME; - public class NativeFormLangUtils { public static String getLanguage(Context context) { @@ -91,6 +91,25 @@ public static String getTranslatedString(String str, Context context) { return translateString(str, ResourceBundle.getBundle(translationsFileName, currLocale)); } + /** + * @param key is the string to translate e.g anc_profile.step4.text + * This key has a first item of anc_profile which is the resource bundle name. For this to work, rename texts with bundle_name as the first item separated by . + * @param context this is the application context which is an instance of Android.intent.Context + * @return The value as a string depending on locale if found + */ + + public static String translateDatabaseString(String key, Context context) { + String resourceBundleName = key.split("\\.")[0].trim(); + Locale currLocale = context == null ? Locale.getDefault() : getLocale(context); + ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName, currLocale); + if (!resourceBundle.containsKey(key)) { + Timber.e("Could not translate String %s. String not found in resource bundle %s ", key, resourceBundleName); + return ""; + } + return resourceBundle.getString(key); + + } + /** * Performs translation on an interpolated {@param str} * i.e. a String containing tokens in the format {{string_name}}, diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormsProperties.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormsProperties.java index 84b0a74df..c31994cba 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormsProperties.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/NativeFormsProperties.java @@ -22,6 +22,8 @@ public Boolean isTrue(String key) { public final static class KEY { //Widgets public static final String WIDGET_DATEPICKER_IS_NUMERIC = "widget.datepicker.is.numeric"; + public static final String WIDGET_VALUE_TRANSLATED = "widget.value.translated"; + } } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/Utils.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/Utils.java index ce91c36cb..4a011ba03 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/Utils.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/utils/Utils.java @@ -1,5 +1,15 @@ package com.vijay.jsonwizard.utils; +import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY; +import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY; +import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY_ID; +import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY_PARENT; +import static com.vijay.jsonwizard.constants.JsonFormConstants.TEXT; +import static com.vijay.jsonwizard.constants.JsonFormConstants.TYPE; +import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; +import static com.vijay.jsonwizard.utils.NativeFormLangUtils.getTranslatedString; +import static com.vijay.jsonwizard.widgets.RepeatingGroupFactory.REFERENCE_EDIT_TEXT_HINT; + import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; @@ -9,10 +19,6 @@ import android.content.DialogInterface; import android.content.res.AssetManager; import android.os.Looper; -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; -import com.google.android.material.snackbar.Snackbar; -import androidx.core.util.TimeUtils; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -23,6 +29,11 @@ import android.widget.RelativeLayout; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; +import androidx.core.util.TimeUtils; + +import com.google.android.material.snackbar.Snackbar; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.customviews.CompoundButton; @@ -67,21 +78,12 @@ import timber.log.Timber; -import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY; -import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY; -import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY_ID; -import static com.vijay.jsonwizard.constants.JsonFormConstants.OPENMRS_ENTITY_PARENT; -import static com.vijay.jsonwizard.constants.JsonFormConstants.TEXT; -import static com.vijay.jsonwizard.constants.JsonFormConstants.TYPE; -import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; -import static com.vijay.jsonwizard.utils.NativeFormLangUtils.getTranslatedString; -import static com.vijay.jsonwizard.widgets.RepeatingGroupFactory.REFERENCE_EDIT_TEXT_HINT; - public class Utils { public final static List PREFICES_OF_INTEREST = Arrays.asList(RuleConstant.PREFIX.GLOBAL, RuleConstant.STEP); public final static Set JAVA_OPERATORS = new HashSet<>( Arrays.asList('(', '!', ',', '?', '+', '-', '*', '/', '%', '+', '-', '.', '^', ')', '<', '>', '=', '{', '}', ':', ';', '[', ']')); + private static final FormUtils formUtils = new FormUtils(); private static ProgressDialog progressDialog; public static void showToast(Context context, String message) { @@ -479,156 +481,25 @@ public static String getFieldKeyPrefix(String stepName, String stepTitle) { return stepName + "#" + stepTitle + ":"; } - public List createExpansionPanelChildren(JSONArray jsonArray) throws JSONException { - List stringList = new ArrayList<>(); - String label; - for (int i = 0; i < jsonArray.length(); i++) { - if (!jsonArray.isNull(i)) { - JSONObject jsonObject = jsonArray.getJSONObject(i); - if (jsonObject.has(JsonFormConstants.VALUES) && jsonObject.has(JsonFormConstants.LABEL) && - !"".equals(jsonObject.getString(JsonFormConstants.LABEL))) { - //Get label and replace any colon in some labels. Not needed at this point - label = jsonObject.getString(JsonFormConstants.LABEL).replace(":", ""); - stringList.add(label + ":" + getStringValue(jsonObject)); - } - } - } - - return stringList; - } - - private String getStringValue(JSONObject jsonObject) throws JSONException { - StringBuilder value = new StringBuilder(); - if (jsonObject != null) { - JSONArray jsonArray = jsonObject.getJSONArray(JsonFormConstants.VALUES); - for (int i = 0; i < jsonArray.length(); i++) { - String stringValue = jsonArray.getString(i); - value.append(getValueFromSecondaryValues(stringValue)); - value.append(", "); - } - } - - return value.toString().replaceAll(", $", ""); - } - - private String getValueFromSecondaryValues(String itemString) { - String[] strings = itemString.split(":"); - return strings.length > 1 ? strings[1] : strings[0]; - } - - protected String getKey(JSONObject object) throws JSONException { - return object.has(RuleConstant.IS_RULE_CHECK) && object.getBoolean(RuleConstant.IS_RULE_CHECK) ? - object.get(RuleConstant.STEP) + "_" + object.get(KEY) : VALUE; - } - - protected Object getValue(JSONObject object) throws JSONException { - Object value; - - if (object.has(VALUE)) { - - value = object.opt(VALUE); - - if (isNumberWidget(object)) { - value = TextUtils.isEmpty(object.optString(VALUE)) ? 0 : - processNumberValues(object.optString(VALUE)); - } else if (value != null && !TextUtils.isEmpty(object.getString(VALUE)) && - canHaveNumber(object)) { - value = processNumberValues(value); - } - - } else { - value = isNumberWidget(object) ? 0 : ""; - } - - return value; - } - - protected boolean isNumberWidget(JSONObject object) throws JSONException { - return object.has(JsonFormConstants.EDIT_TYPE) && - object.getString(JsonFormConstants.EDIT_TYPE).equals(JsonFormConstants.EDIT_TEXT_TYPE.NUMBER) || - object.getString(TYPE).equals(JsonFormConstants.NUMBER_SELECTOR); - } - - protected Object processNumberValues(Object object) { - Object value = object; - try { - if (value.toString().contains(".")) { - value = String.valueOf((float) Math.round(Float.valueOf(value.toString()) * 100) / 100); - } else { - value = Integer.valueOf(value.toString()); - } - } catch (NumberFormatException e) { - Timber.e(e); - } - return value; - } - - protected boolean canHaveNumber(JSONObject object) throws JSONException { - return isNumberWidget(object) || object.getString(TYPE).equals(JsonFormConstants.HIDDEN) || - object.getString(TYPE).equals(JsonFormConstants.SPINNER); - } - - public void setChildKey(View view, String type, ExpansionPanelGenericPopupDialog genericPopupDialog) { - String childKey; - if (type != null && (type.equals(JsonFormConstants.CHECK_BOX) || type.equals(JsonFormConstants.NATIVE_RADIO_BUTTON) || type.equals(JsonFormConstants.EXTENDED_RADIO_BUTTON))) { - childKey = (String) view.getTag(com.vijay.jsonwizard.R.id.childKey); - genericPopupDialog.setChildKey(childKey); - } - } - - public void setExpansionPanelDetails(String type, String toolbarHeader, String container, ExpansionPanelGenericPopupDialog genericPopupDialog) { - if (type != null && type.equals(JsonFormConstants.EXPANSION_PANEL)) { - genericPopupDialog.setHeader(toolbarHeader); - genericPopupDialog.setContainer(container); - } - } - /** - * Gets the {@link androidx.fragment.app.FragmentTransaction} from the {@link Context} and removes any {@link androidx.fragment.app.Fragment} with the tag `GenericPopup` from the transaction. - * Then nullifies the stack by calling {@link androidx.fragment.app.FragmentTransaction#addToBackStack(String)} with a null value. + * Returns the value string value for special translated fields like the Native Radio Button, Spinner, Check Box e.tc * - * @param context {@link Activity} The activity context where this transaction called from - * @return fragmentTransaction {@link androidx.fragment.app.FragmentTransaction} + * @param jsonObject -- Widget #JSONObject + * @return */ - @NotNull - public FragmentTransaction getFragmentTransaction(Activity context) { - FragmentTransaction fragmentTransaction = context.getFragmentManager().beginTransaction(); - Fragment fragment = context.getFragmentManager().findFragmentByTag("GenericPopup"); - if (fragment != null) { - fragmentTransaction.remove(fragment); + public static String returnValue(JSONObject jsonObject) { + String value = ""; + if (enabledProperty(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED) && jsonObject.has(TYPE) && jsonObject.optString(TYPE).equals(JsonFormConstants.NATIVE_RADIO_BUTTON)) { + JSONObject valueObject = jsonObject.optJSONObject(VALUE); + if (valueObject != null) { + value = valueObject.optString(VALUE, ""); + } + } else { + value = jsonObject.optString(VALUE, ""); } - - fragmentTransaction.addToBackStack(null); - return fragmentTransaction; - } - - /** - * Enabling the expansion panel views after they were disabled on sub form opening. - * - * @param linearLayout {@link LinearLayout} - */ - public void enableExpansionPanelViews(LinearLayout linearLayout) { - RelativeLayout layoutHeader = (RelativeLayout) linearLayout.getChildAt(0); - RelativeLayout expansionHeaderLayout = layoutHeader.findViewById(R.id.expansion_header_layout); - expansionHeaderLayout.setEnabled(true); - expansionHeaderLayout.setClickable(true); - - ImageView statusImageView = expansionHeaderLayout.findViewById(R.id.statusImageView); - statusImageView.setEnabled(true); - statusImageView.setClickable(true); - - CustomTextView topBarTextView = expansionHeaderLayout.findViewById(R.id.topBarTextView); - topBarTextView.setClickable(true); - topBarTextView.setEnabled(true); - - LinearLayout contentLayout = (LinearLayout) linearLayout.getChildAt(1); - LinearLayout buttonLayout = contentLayout.findViewById(R.id.accordion_bottom_navigation); - Button okButton = buttonLayout.findViewById(R.id.ok_button); - okButton.setEnabled(true); - okButton.setClickable(true); + return value; } - @NonNull private static String cleanToken(String conditionTokenRaw) { String conditionToken = conditionTokenRaw.trim(); @@ -752,7 +623,6 @@ public static String getFileContentsAsString(File file) { return fileContents; } - /** * Converts an {@link InputStream} into a {@link String} * @@ -766,7 +636,6 @@ public static String convertStreamToString(InputStream inputStream) { return data; } - /** * Gets form config entries as specified in json.form.config.json * @@ -884,7 +753,6 @@ public static String formatDateToPattern(String date, String inputFormat, String return sdf.format(newDate); } - public static int getResourceId(Context context, String name, ResourceType resourceType) { try { return context.getResources().getIdentifier(name, resourceType.getType(), context.getPackageName()); @@ -921,7 +789,6 @@ public static boolean isEmptyJsonObject(JSONObject jsonObject) { return jsonObject == null || jsonObject.length() == 0; } - /** * Returns the object that holds the repeating group count * @@ -952,6 +819,211 @@ public static JSONObject getRepeatingGroupCountObj(@NotNull WidgetArgs widgetArg stepFields.put(repeatingGroupCountObj); return repeatingGroupCountObj; } + + + /** + * @param This function is to return JSON Object of i.e {"value":"widget_item_key","text":"translated_text_value"} for translatable_widgets_keys. It's not specific to the widget_type + * @param item + * @param itemType + * @return + * @throws JSONException + */ + + public static JSONObject generateTranslatableValue(String value, JSONObject item) throws JSONException { + JSONObject newValue = new JSONObject(); + if (item.has(JsonFormConstants.OPTIONS_FIELD_NAME)) { + JSONArray options = item.getJSONArray(JsonFormConstants.OPTIONS_FIELD_NAME); + JSONObject selectedOption = formUtils.getOptionFromOptionsUsingKey(options, value); + newValue.put(VALUE, value); + newValue.put(TEXT, selectedOption.optString(JsonFormConstants.TRANSLATION_TEXT)); + return newValue; + } + newValue.put(VALUE, value); + newValue.put(TEXT, item.optString(JsonFormConstants.TRANSLATION_TEXT)); + return newValue; + } + + public static boolean enabledProperty(String appPropName) { + NativeFormsProperties nativeFormsProperties = JsonFormFragment.getNativeFormProperties(); + return nativeFormsProperties != null && nativeFormsProperties.isTrue(appPropName); + } + + public static String getValueAfterTranslation(JSONObject item) { + try { + if (item != null && item.has(VALUE)) { + if (item.opt(VALUE) != null && item.opt(VALUE).toString().length() > 0 && item.opt(VALUE).toString().charAt(0) == '{') { + return new JSONObject(item.opt(VALUE).toString()).optString(VALUE); + } + return item.opt(VALUE) + ""; + } + return ""; + } catch (Exception e) { + Timber.e(e); + return ""; + } + } + + public List createExpansionPanelChildren(JSONArray jsonArray) throws JSONException { + List stringList = new ArrayList<>(); + String label; + for (int i = 0; i < jsonArray.length(); i++) { + if (!jsonArray.isNull(i)) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + if (jsonObject.has(JsonFormConstants.VALUES) && jsonObject.has(JsonFormConstants.LABEL) && + !"".equals(jsonObject.getString(JsonFormConstants.LABEL))) { + //Get label and replace any colon in some labels. Not needed at this point + label = jsonObject.getString(JsonFormConstants.LABEL).replace(":", ""); + stringList.add(label + ":" + getStringValue(jsonObject)); + } + } + } + + return stringList; + } + + private String getStringValue(JSONObject jsonObject) throws JSONException { + StringBuilder value = new StringBuilder(); + if (jsonObject != null) { + JSONArray jsonArray = jsonObject.getJSONArray(JsonFormConstants.VALUES); + for (int i = 0; i < jsonArray.length(); i++) { + String stringValue = jsonArray.getString(i); + value.append(getValueFromSecondaryValues(stringValue)); + value.append(", "); + } + } + + return value.toString().replaceAll(", $", ""); + } + + private String getValueFromSecondaryValues(String itemString) { + String[] strings = itemString.split(":"); + return strings.length > 1 ? strings[1] : strings[0]; + } + + protected String getKey(JSONObject object) throws JSONException { + return object.has(RuleConstant.IS_RULE_CHECK) && object.getBoolean(RuleConstant.IS_RULE_CHECK) ? + object.get(RuleConstant.STEP) + "_" + object.get(KEY) : VALUE; + } + + protected Object getValue(JSONObject object) throws JSONException { + Object value; + if (object.has(VALUE)) { + value = returnValue(object); + if (isNumberWidget(object)) { + value = TextUtils.isEmpty(object.optString(VALUE)) ? 0 : + processNumberValues(object.optString(VALUE)); + } else if (value != null && !TextUtils.isEmpty(object.getString(VALUE)) && + canHaveNumber(object)) { + value = processNumberValues(value); + } + + } else { + value = isNumberWidget(object) ? 0 : ""; + } + + return value; + } + + protected boolean isNumberWidget(JSONObject object) throws JSONException { + return object.has(JsonFormConstants.EDIT_TYPE) && + object.getString(JsonFormConstants.EDIT_TYPE).equals(JsonFormConstants.EDIT_TEXT_TYPE.NUMBER) || + object.getString(TYPE).equals(JsonFormConstants.NUMBER_SELECTOR); + } + + protected Object processNumberValues(Object object) { + Object value = object; + try { + if (value.toString().contains(".")) { + value = String.valueOf((float) Math.round(Float.valueOf(value.toString()) * 100) / 100); + } else { + value = Integer.valueOf(value.toString()); + } + } catch (NumberFormatException e) { + Timber.e(e); + } + return value; + } + + protected boolean canHaveNumber(JSONObject object) throws JSONException { + return isNumberWidget(object) || object.getString(TYPE).equals(JsonFormConstants.HIDDEN) || + object.getString(TYPE).equals(JsonFormConstants.SPINNER); + } + + public void setChildKey(View view, String type, ExpansionPanelGenericPopupDialog genericPopupDialog) { + String childKey; + if (type != null && (type.equals(JsonFormConstants.CHECK_BOX) || type.equals(JsonFormConstants.NATIVE_RADIO_BUTTON) || type.equals(JsonFormConstants.EXTENDED_RADIO_BUTTON))) { + childKey = (String) view.getTag(com.vijay.jsonwizard.R.id.childKey); + genericPopupDialog.setChildKey(childKey); + } + } + + public void setExpansionPanelDetails(String type, String toolbarHeader, String container, ExpansionPanelGenericPopupDialog genericPopupDialog) { + if (type != null && type.equals(JsonFormConstants.EXPANSION_PANEL)) { + genericPopupDialog.setHeader(toolbarHeader); + genericPopupDialog.setContainer(container); + } + } + + /** + * Gets the {@link android.support.v4.app.FragmentTransaction} from the {@link Context} and removes any {@link android.support.v4.app.Fragment} with the tag `GenericPopup` from the transaction. + * Then nullifies the stack by calling {@link android.support.v4.app.FragmentTransaction#addToBackStack(String)} with a null value. + * + * @param context {@link Activity} The activity context where this transaction called from + * @return fragmentTransaction {@link android.support.v4.app.FragmentTransaction} + */ + @NotNull + public FragmentTransaction getFragmentTransaction(Activity context) { + FragmentTransaction fragmentTransaction = context.getFragmentManager().beginTransaction(); + Fragment fragment = context.getFragmentManager().findFragmentByTag("GenericPopup"); + if (fragment != null) { + fragmentTransaction.remove(fragment); + } + + fragmentTransaction.addToBackStack(null); + return fragmentTransaction; + } + + /** + * Enabling the expansion panel views after they were disabled on sub form opening. + * + * @param linearLayout {@link LinearLayout} + */ + public void enableExpansionPanelViews(LinearLayout linearLayout) { + RelativeLayout layoutHeader = (RelativeLayout) linearLayout.getChildAt(0); + RelativeLayout expansionHeaderLayout = layoutHeader.findViewById(R.id.expansion_header_layout); + expansionHeaderLayout.setEnabled(true); + expansionHeaderLayout.setClickable(true); + + ImageView statusImageView = expansionHeaderLayout.findViewById(R.id.statusImageView); + statusImageView.setEnabled(true); + statusImageView.setClickable(true); + + CustomTextView topBarTextView = expansionHeaderLayout.findViewById(R.id.topBarTextView); + topBarTextView.setClickable(true); + topBarTextView.setEnabled(true); + + LinearLayout contentLayout = (LinearLayout) linearLayout.getChildAt(1); + LinearLayout buttonLayout = contentLayout.findViewById(R.id.accordion_bottom_navigation); + Button okButton = buttonLayout.findViewById(R.id.ok_button); + okButton.setEnabled(true); + okButton.setClickable(true); + } + + public static String extractValueFromJson(String value) + { + try{ + if(!StringUtils.isEmpty(value) && value.startsWith("{") && value.endsWith("}")) { + JSONObject object = new JSONObject(value); + return object.optString(VALUE); + } + } + catch (Exception e) + { + Timber.e(e); + } + return value; + } + } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BarcodeFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BarcodeFactory.java index d297cc096..eeab9a1b4 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BarcodeFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BarcodeFactory.java @@ -72,17 +72,14 @@ public List getViewsFromJson(final String stepName, final Context context, List views = new ArrayList<>(1); final RelativeLayout rootLayout = getRootLayout(context); final int canvasId = ViewUtil.generateViewId(); - formFragment.getJsonApi().getAppExecutors().mainThread().execute(new Runnable() { - @Override - public void run() { - try { - rootLayout.setId(canvasId); - final MaterialEditText editText = createEditText(rootLayout, jsonObject, canvasId, stepName, popup); - attachJson(rootLayout, stepName, context, formFragment, jsonObject, editText); - ((JsonApi) context).addFormDataView(editText); - } catch (JSONException e) { - Timber.e(e); - } + formFragment.getJsonApi().getAppExecutors().mainThread().execute(() -> { + try { + rootLayout.setId(canvasId); + final MaterialEditText editText = createEditText(rootLayout, jsonObject, canvasId, stepName, popup); + attachJson(rootLayout, stepName, context, formFragment, jsonObject, editText); + ((JsonApi) context).addFormDataView(editText); + } catch (JSONException e) { + Timber.e(e); } }); views.add(rootLayout); diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactory.java index 7bf0a7c65..51865a422 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactory.java @@ -1,37 +1,43 @@ package com.vijay.jsonwizard.widgets; +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; +import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; +import static com.vijay.jsonwizard.utils.Utils.hideProgressDialog; +import static com.vijay.jsonwizard.utils.Utils.showProgressDialog; +import static edu.washington.cs.ubicomplab.rdt_reader.core.Constants.SAVED_IMAGE_FILE_PATH; + import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; -import android.os.AsyncTask; -import androidx.core.content.ContextCompat; import android.util.Log; +import androidx.core.content.ContextCompat; + import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.interfaces.JsonApi; +import com.vijay.jsonwizard.utils.AppExecutors; import org.json.JSONException; import edu.washington.cs.ubicomplab.rdt_reader.activity.RDTCaptureActivity; -import static android.app.Activity.RESULT_CANCELED; -import static android.app.Activity.RESULT_OK; -import static com.vijay.jsonwizard.constants.JsonFormConstants.VALUE; -import static com.vijay.jsonwizard.utils.Utils.hideProgressDialog; -import static com.vijay.jsonwizard.utils.Utils.showProgressDialog; -import static edu.washington.cs.ubicomplab.rdt_reader.core.Constants.SAVED_IMAGE_FILE_PATH; - /** * Created by Vincent Karuri on 17/06/2020 */ public class BasicRDTCaptureFactory extends RDTCaptureFactory { private static final String TAG = BasicRDTCaptureFactory.class.getName(); + private AppExecutors appExecutors; - private class LaunchRDTCameraTask extends AsyncTask { + protected void launchRDTCaptureActivity() { + if (isPermissionGiven()) { + new LaunchRDTCameraTask().init(); + } + } - @Override + private class LaunchRDTCameraTask { protected Void doInBackground(Void... voids) { Activity activity = (Activity) widgetArgs.getContext(); Intent intent = new Intent(activity, RDTCaptureActivity.class); @@ -39,15 +45,14 @@ protected Void doInBackground(Void... voids) { return null; } - @Override protected void onPreExecute() { showProgressDialog(R.string.please_wait_title, R.string.launching_rdt_capture_message, widgetArgs.getContext()); } - } - protected void launchRDTCaptureActivity() { - if (isPermissionGiven()) { - new LaunchRDTCameraTask().execute(); + public void init() { + appExecutors =new AppExecutors(); + appExecutors.mainThread().execute(this::onPreExecute); + appExecutors.diskIO().execute(this::doInBackground); } } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/ButtonFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/ButtonFactory.java index 537856349..c6751e55e 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/ButtonFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/ButtonFactory.java @@ -128,35 +128,32 @@ private void setUpButtonActions(final JsonApi context, final JsonFormFragment fo jsonObject.put(JsonFormConstants.VALUE, Boolean.FALSE.toString()); jsonObject.getJSONObject(JsonFormConstants.ACTION).put(JsonFormConstants.RESULT, false); final String behaviour = action.optString(JsonFormConstants.BEHAVIOUR); - button.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - String addressString = (String) v.getTag(R.id.address); - if (!TextUtils.isEmpty(addressString)) { - String[] address = addressString.split(":"); - JSONObject jsonObject = context - .getObjectUsingAddress(address, false); - jsonObject.put(JsonFormConstants.VALUE, Boolean.TRUE.toString()); - - switch (behaviour) { - case JsonFormConstants.BEHAVIOUR_FINISH_FORM: - button.setTag(R.id.raw_value, Boolean.TRUE.toString()); - formFragment.save(confirmationBtnSkipValidation); - break; - case JsonFormConstants.BEHAVIOUR_NEXT_STEP: - formFragment.next(); - break; - default: - jsonObject.getJSONObject(JsonFormConstants.ACTION) - .put(JsonFormConstants.RESULT, false); - jsonObject.put(JsonFormConstants.VALUE, Boolean.FALSE.toString()); - break; - } + button.setOnClickListener(v -> { + try { + String addressString = (String) v.getTag(R.id.address); + if (!TextUtils.isEmpty(addressString)) { + String[] address = addressString.split(":"); + JSONObject jsonObject1 = context + .getObjectUsingAddress(address, false); + jsonObject1.put(JsonFormConstants.VALUE, Boolean.TRUE.toString()); + + switch (behaviour) { + case JsonFormConstants.BEHAVIOUR_FINISH_FORM: + button.setTag(R.id.raw_value, Boolean.TRUE.toString()); + formFragment.save(confirmationBtnSkipValidation); + break; + case JsonFormConstants.BEHAVIOUR_NEXT_STEP: + formFragment.next(); + break; + default: + jsonObject1.getJSONObject(JsonFormConstants.ACTION) + .put(JsonFormConstants.RESULT, false); + jsonObject1.put(JsonFormConstants.VALUE, Boolean.FALSE.toString()); + break; } - } catch (JSONException e) { - e.printStackTrace(); } + } catch (JSONException e) { + e.printStackTrace(); } }); } else { diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/CheckBoxFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/CheckBoxFactory.java index aadfccdd6..26a39ef7b 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/CheckBoxFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/CheckBoxFactory.java @@ -1,10 +1,14 @@ package com.vijay.jsonwizard.widgets; +import static com.vijay.jsonwizard.utils.FormUtils.MATCH_PARENT; +import static com.vijay.jsonwizard.utils.FormUtils.WRAP_CONTENT; +import static com.vijay.jsonwizard.utils.FormUtils.getCurrentCheckboxValues; +import static com.vijay.jsonwizard.utils.FormUtils.getLinearLayoutParams; +import static com.vijay.jsonwizard.utils.FormUtils.getValueFromSpOrDpOrPx; + import android.app.Activity; import android.content.Context; import android.graphics.Color; -import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -12,6 +16,9 @@ import android.widget.ImageView; import android.widget.LinearLayout; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + import com.rey.material.util.ViewUtil; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; @@ -20,6 +27,7 @@ import com.vijay.jsonwizard.interfaces.CommonListener; import com.vijay.jsonwizard.interfaces.JsonApi; import com.vijay.jsonwizard.utils.FormUtils; +import com.vijay.jsonwizard.utils.Utils; import com.vijay.jsonwizard.utils.ValidationStatus; import com.vijay.jsonwizard.views.JsonFormFragmentView; @@ -32,21 +40,16 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import timber.log.Timber; -import static com.vijay.jsonwizard.utils.FormUtils.MATCH_PARENT; -import static com.vijay.jsonwizard.utils.FormUtils.WRAP_CONTENT; -import static com.vijay.jsonwizard.utils.FormUtils.getCurrentCheckboxValues; -import static com.vijay.jsonwizard.utils.FormUtils.getLinearLayoutParams; -import static com.vijay.jsonwizard.utils.FormUtils.getValueFromSpOrDpOrPx; - /** * Created by vijay on 24-05-2015. */ public class CheckBoxFactory extends BaseFactory { - private FormUtils formUtils = new FormUtils(); + private final FormUtils formUtils = new FormUtils(); public static ValidationStatus validate(JsonFormFragmentView formFragmentView, LinearLayout checkboxLinearLayout) { String error = (String) checkboxLinearLayout.getTag(R.id.error); @@ -59,7 +62,7 @@ public static ValidationStatus validate(JsonFormFragmentView formFragmentView, L return new ValidationStatus(true, null, formFragmentView, checkboxLinearLayout); } - public static boolean isValid(final LinearLayout checkboxLinearLayout){ + public static boolean isValid(final LinearLayout checkboxLinearLayout) { boolean isRequired = checkboxLinearLayout.isEnabled() && checkboxLinearLayout.getTag(R.id.error) != null; return !isRequired || performValidation(checkboxLinearLayout); } @@ -150,7 +153,7 @@ private List attachJson(final String stepName, final Context context, fina } } - formUtils.updateValueToJSONArray(jsonObject, jsonObject.optString(JsonFormConstants.VALUE, "")); + formUtils.updateValueToJSONArray(jsonObject, Utils.returnValue(jsonObject)); attachRefreshLogic(jsonObject, context, rootLayout); rootLayout.setTag(R.id.canvas_ids, canvasIds.toString()); @@ -226,20 +229,25 @@ private ArrayList addCheckBoxOptionsElements(Boolean readOnly, @Override public void run() { if (StringUtils.isNotEmpty(item.optString(JsonFormConstants.VALUE))) { - widgetArgs.getFormFragment().getJsonApi().getAppExecutors().mainThread().execute(new Runnable() { - @Override - public void run() { - checkBox.setChecked(Boolean.parseBoolean(item.optString(JsonFormConstants.VALUE))); + widgetArgs.getFormFragment().getJsonApi().getAppExecutors().mainThread().execute(() -> checkBox.setChecked(Boolean.parseBoolean(item.optString(JsonFormConstants.VALUE)))); + } else { + //Preselect values if they exist + try { + if (finalCheckBoxValues != null) { + HashSet translatedCheckBox = new HashSet<>(); + for (String checkBoxVal : Objects.requireNonNull(getCurrentCheckboxValues(finalCheckBoxValues))) { + if (checkBoxVal != null && checkBoxVal.startsWith("{")) { + JSONObject jsonObject = new JSONObject(checkBoxVal); + translatedCheckBox.add(jsonObject.optString(JsonFormConstants.VALUE)); + } + } + if ((translatedCheckBox.size() > 0 && translatedCheckBox.contains(item.getString(JsonFormConstants.KEY))) || getCurrentCheckboxValues(finalCheckBoxValues).contains(item.getString(JsonFormConstants.KEY))) { + checkBox.setChecked(true); + } } - }); - } - //Preselect values if they exist - try { - if (finalCheckBoxValues != null && getCurrentCheckboxValues(finalCheckBoxValues).contains(item.getString(JsonFormConstants.KEY))) { - checkBox.setChecked(true); + } catch (JSONException e) { + Timber.e(e); } - } catch (JSONException e) { - Timber.e(e); } } }); diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactory.java index 53807b4c6..ad4d459b0 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactory.java @@ -1,5 +1,8 @@ + package com.vijay.jsonwizard.widgets; +import static com.vijay.jsonwizard.widgets.DatePickerFactory.DATE_FORMAT; + import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; @@ -7,11 +10,7 @@ import android.content.Intent; import android.graphics.Color; import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.ConstraintLayout; import android.text.TextUtils; -import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; @@ -24,6 +23,10 @@ import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; + import com.rey.material.util.ViewUtil; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.activities.JsonFormActivity; @@ -34,6 +37,7 @@ import com.vijay.jsonwizard.interfaces.FormWidgetFactory; import com.vijay.jsonwizard.interfaces.JsonApi; import com.vijay.jsonwizard.utils.FormUtils; +import com.vijay.jsonwizard.utils.Utils; import com.vijay.jsonwizard.utils.ValidationStatus; import com.vijay.jsonwizard.views.CustomTextView; import com.vijay.jsonwizard.views.JsonFormFragmentView; @@ -54,8 +58,6 @@ import timber.log.Timber; -import static com.vijay.jsonwizard.widgets.DatePickerFactory.DATE_FORMAT; - /** * Created by samuelgithengi on 8/16/18. @@ -63,7 +65,8 @@ public class NativeRadioButtonFactory implements FormWidgetFactory { private static final String TAG = NativeRadioButtonFactory.class.getCanonicalName(); - private FormUtils formUtils = new FormUtils(); + private final FormUtils formUtils = new FormUtils(); + private final CustomTextViewClickListener customTextViewClickListener = new CustomTextViewClickListener(); private RadioButton radioButton; private CustomTextView extraInfoTextView; private CustomTextView specifyTextView; @@ -72,7 +75,6 @@ public class NativeRadioButtonFactory implements FormWidgetFactory { private JsonFormFragment formFragment; private String stepName; private JSONArray canvasIds; - private CustomTextViewClickListener customTextViewClickListener = new CustomTextViewClickListener(); public static void showDateDialog(View view) { Context context = (Context) view.getTag(R.id.specify_context); @@ -108,7 +110,7 @@ public static void showDateDialog(View view) { } } catch (JSONException e) { - Log.e(TAG, e.getMessage(), e); + Timber.e(e); } } @@ -166,7 +168,7 @@ public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth assignHiddenDateValue(widget, calendarDate); } } catch (JSONException e) { - Log.i(TAG, Log.getStackTraceString(e)); + Timber.e(e); } } } @@ -221,7 +223,7 @@ private static void assignHiddenDateValue(JSONObject widget, Calendar calendarDa try { widget.put(JsonFormConstants.VALUE, DATE_FORMAT.format(calendarDate.getTime())); } catch (Exception e) { - Log.i(TAG, Log.getStackTraceString(e)); + Timber.e(e); } } @@ -567,14 +569,16 @@ private void createRadioButton(RelativeLayout rootLayout, JSONObject jsonObject, if (radioButton != null) { setRadioButtonTags(rootLayout, jsonObject, item, extraInfo, radioButton); - if (!TextUtils.isEmpty(jsonObject.optString(JsonFormConstants.VALUE)) && - jsonObject.optString(JsonFormConstants.VALUE).equals(item.getString(JsonFormConstants.KEY))) { - ((Activity) context).runOnUiThread(new Runnable() { - @Override - public void run() { - radioButton.setChecked(true); - } - }); + String valueString = jsonObject.optString(JsonFormConstants.VALUE); + if(valueString != null && valueString.startsWith("{")) + { + JSONObject translationObject = new JSONObject(valueString); + valueString = translationObject.optString(JsonFormConstants.VALUE); + } + + if (!TextUtils.isEmpty(valueString) && + valueString.equals(item.getString(JsonFormConstants.KEY))) { + ((Activity) context).runOnUiThread(() -> radioButton.setChecked(true)); } String optionTextColor = JsonFormConstants.DEFAULT_TEXT_COLOR; if (item.has(JsonFormConstants.TEXT_COLOR)) { @@ -606,21 +610,29 @@ public void run() { radioButton.setEnabled(!readOnly); // Make sure to register listener after setting the value to avoid unnecessary onCheckedChange call - if (StringUtils.isNotBlank(jsonObject.optString(JsonFormConstants.VALUE)) && - jsonObject.optString(JsonFormConstants.VALUE).equals(item.getString(JsonFormConstants.KEY))) { - ((Activity) context).runOnUiThread(new Runnable() { - @Override - public void run() { - radioButton.setChecked(true); - radioButton.setOnCheckedChangeListener(listener); - } + checkSelectedRadioButton(listener, radioButton, Utils.returnValue(jsonObject), item); + } + } + + private void checkSelectedRadioButton(final CommonListener listener, final RadioButton radioButton, String value, JSONObject item) throws JSONException { + if (StringUtils.isNotBlank(value)) { + JSONObject jsonObject = null; + if (StringUtils.isNotBlank(value) && value.startsWith("{")) { + jsonObject = new JSONObject(value); + } + if (value.equals(item.getString(JsonFormConstants.KEY)) || (jsonObject != null && jsonObject.has(JsonFormConstants.VALUE) && jsonObject.optString(JsonFormConstants.VALUE).equals(item.getString(JsonFormConstants.KEY)))) { + ((Activity) context).runOnUiThread(() -> { + radioButton.setChecked(true); }); - } else { - radioButton.setOnCheckedChangeListener(listener); } + radioButton.setOnCheckedChangeListener(listener); + } else { + radioButton.setOnCheckedChangeListener(listener); } + } + private void setRadioButtonTags(RelativeLayout rootLayout, JSONObject jsonObject, JSONObject item, String extraInfo, RadioButton radioButton) throws JSONException { String openMrsEntityParent = jsonObject.getString(JsonFormConstants.OPENMRS_ENTITY_PARENT); @@ -670,7 +682,7 @@ private void createSpecifyTextView(RelativeLayout rootLayout, final CommonListen JsonFormFragment formFragment, String stepName) throws JSONException { String optionKey = item.optString(JsonFormConstants.KEY, ""); - String widgetValue = jsonObject.optString(JsonFormConstants.VALUE, ""); + String widgetValue = Utils.returnValue(jsonObject); String specifyText; if (item.has(JsonFormConstants.SECONDARY_VALUE) && widgetValue.equals(optionKey)) @@ -702,7 +714,7 @@ private void createSpecifyTextView(RelativeLayout rootLayout, final CommonListen private String getOptionTextWithSecondaryValue(JSONObject item, JSONObject jsonObject) throws JSONException { String optionText = item.getString(JsonFormConstants.TEXT); String optionKey = item.getString(JsonFormConstants.KEY); - String widgetValue = jsonObject.optString(JsonFormConstants.VALUE, ""); + String widgetValue = Utils.returnValue(jsonObject); if (optionKey.equals(widgetValue) && item.has(JsonFormConstants.SECONDARY_VALUE)) { JSONArray secondaryValueArray = item.getJSONArray(JsonFormConstants.SECONDARY_VALUE); @@ -781,7 +793,7 @@ private void createSpecifyReasonsDisplayTextView(RelativeLayout rootLayout, JSON String popupReasonsText = ""; CustomTextView reasonsTextView = rootLayout.findViewById(R.id.reasonsTextView); String optionKey = item.optString(JsonFormConstants.KEY, ""); - String widgetValue = jsonObject.optString(JsonFormConstants.VALUE, ""); + String widgetValue = Utils.returnValue(jsonObject); if (widgetValue.equals(optionKey)) { if (item.has(JsonFormConstants.SECONDARY_VALUE)) { popupReasonsText = formUtils.getSpecifyText(item.getJSONArray(JsonFormConstants.SECONDARY_VALUE)); @@ -871,15 +883,6 @@ private void setRadioButton(RadioButton radioButton) { this.radioButton = radioButton; } - private class CustomTextViewClickListener implements View.OnClickListener { - @Override - public void onClick(View view) { - RadioButton radioButton = (RadioButton) view.getTag(R.id.native_radio_button); - radioButton.setChecked(false); - radioButton.performClick(); - } - } - @Override @NonNull public Set getCustomTranslatableWidgetFields() { @@ -891,7 +894,7 @@ public Set getCustomTranslatableWidgetFields() { return customTranslatableWidgetFields; } - public void cleanUp(){ + public void cleanUp() { this.context = null; this.formFragment = null; this.radioButton = null; @@ -899,4 +902,14 @@ public void cleanUp(){ this.specifyTextView = null; this.reasonsTextView = null; } + + + private class CustomTextViewClickListener implements View.OnClickListener { + @Override + public void onClick(View view) { + RadioButton radioButton = (RadioButton) view.getTag(R.id.native_radio_button); + radioButton.setChecked(false); + radioButton.performClick(); + } + } } diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RadioButtonFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RadioButtonFactory.java index 9db4e1061..a21f09b31 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RadioButtonFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RadioButtonFactory.java @@ -1,5 +1,11 @@ package com.vijay.jsonwizard.widgets; +import static com.vijay.jsonwizard.utils.FormUtils.FONT_BOLD_PATH; +import static com.vijay.jsonwizard.utils.FormUtils.MATCH_PARENT; +import static com.vijay.jsonwizard.utils.FormUtils.WRAP_CONTENT; +import static com.vijay.jsonwizard.utils.FormUtils.getLinearLayoutParams; +import static com.vijay.jsonwizard.utils.FormUtils.getTextViewWith; + import android.content.Context; import androidx.annotation.NonNull; import android.text.TextUtils; @@ -25,12 +31,6 @@ import java.util.List; import java.util.Set; -import static com.vijay.jsonwizard.utils.FormUtils.FONT_BOLD_PATH; -import static com.vijay.jsonwizard.utils.FormUtils.MATCH_PARENT; -import static com.vijay.jsonwizard.utils.FormUtils.WRAP_CONTENT; -import static com.vijay.jsonwizard.utils.FormUtils.getLinearLayoutParams; -import static com.vijay.jsonwizard.utils.FormUtils.getTextViewWith; - /** * Created by vijay on 24-05-2015. */ @@ -76,10 +76,16 @@ public List getViewsFromJson(String stepName, Context context, JsonFormFra radioButton.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY)); // radioButton.setTextSize(context.getResources().getDimension(R.dimen.default_text_size)); radioButton.setOnCheckedChangeListener(listener); - if (!TextUtils.isEmpty(jsonObject.optString(JsonFormConstants.VALUE)) - && jsonObject.optString(JsonFormConstants.VALUE).equals(item.getString(JsonFormConstants.KEY))) { - radioButton.setChecked(true); + if (!TextUtils.isEmpty(jsonObject.optString(JsonFormConstants.VALUE))) { + JSONObject translatedObject = null; + if (jsonObject.optString(JsonFormConstants.VALUE).startsWith("{")) { + translatedObject = new JSONObject(jsonObject.optString(JsonFormConstants.VALUE)); + } + if (jsonObject.optString(JsonFormConstants.VALUE).equals(item.getString(JsonFormConstants.KEY)) || (translatedObject != null && translatedObject.optString(JsonFormConstants.VALUE).equals(item.optString(JsonFormConstants.KEY)))) { + radioButton.setChecked(true); + } } + radioButton.setEnabled(!readOnly); radioButton.setFocusable(!readOnly); textView.setEnabled(!readOnly); diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactory.java index 98526f013..efc2bb693 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactory.java @@ -383,7 +383,7 @@ private void attachRepeatingGroup(final ViewParent parent, final int numRepeatin } new AttachRepeatingGroupTask(parent, numRepeatingGroups, repeatingGroupLayouts, - widgetArgs, doneButton).execute(); + widgetArgs, doneButton).init(); } protected int getLayout() { diff --git a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/SpinnerFactory.java b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/SpinnerFactory.java index a2b709885..ba75cdc92 100644 --- a/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/SpinnerFactory.java +++ b/android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/SpinnerFactory.java @@ -2,8 +2,6 @@ import android.content.Context; import android.graphics.Color; -import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; @@ -15,6 +13,9 @@ import android.widget.ImageView; import android.widget.RelativeLayout; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + import com.rey.material.util.ViewUtil; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; @@ -26,6 +27,7 @@ import com.vijay.jsonwizard.utils.ValidationStatus; import com.vijay.jsonwizard.views.JsonFormFragmentView; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.json.JSONArray; import org.json.JSONException; @@ -40,7 +42,7 @@ * Created by nipun on 30/05/15. */ public class SpinnerFactory extends BaseFactory { - private FormUtils formUtils = new FormUtils(); + private final FormUtils formUtils = new FormUtils(); public static ValidationStatus validate(JsonFormFragmentView formFragmentView, MaterialSpinner spinner) { if (spinner.getTag(R.id.v_required) == null) { @@ -166,6 +168,11 @@ private void addSpinner(JSONObject jsonObject, RelativeLayout spinnerRelativeLay indexToSelect = i; } else if (keysJson != null && valueToSelect.equals(keysJson.optString(i))) { indexToSelect = i; + } else if (keysJson != null && StringUtils.isNotBlank(valueToSelect) && valueToSelect.startsWith("{")) { + JSONObject valueObject = new JSONObject(valueToSelect); + if (valueObject.has(JsonFormConstants.VALUE) && valueObject.optString(JsonFormConstants.VALUE).equals(keysJson.optString(i))) { + indexToSelect = i; + } } } } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/activities/JsonFormActivityTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/activities/JsonFormActivityTest.java index 5d0b7211f..43bebf226 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/activities/JsonFormActivityTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/activities/JsonFormActivityTest.java @@ -1,9 +1,10 @@ package com.vijay.jsonwizard.activities; +import static org.junit.Assert.assertEquals; + +import android.app.Application; import android.content.Context; import android.content.Intent; -import androidx.core.util.Pair; -import androidx.appcompat.widget.AppCompatRadioButton; import android.text.Html; import android.text.Spanned; import android.view.View; @@ -13,6 +14,9 @@ import android.widget.RadioGroup; import android.widget.RelativeLayout; +import androidx.appcompat.widget.AppCompatRadioButton; +import androidx.core.util.Pair; + import com.rengwuxian.materialedittext.MaterialEditText; import com.rey.material.util.ViewUtil; import com.vijay.jsonwizard.NativeFormLibrary; @@ -34,6 +38,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatchers; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.powermock.reflect.Whitebox; @@ -52,22 +57,24 @@ import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertEquals; - public class JsonFormActivityTest extends BaseActivityTest { private JsonFormActivity activity; private ActivityController controller; private final TestUtils testUtils = new TestUtils(); + @Mock + private Context context; + private Intent intent; + @Before public void setUp() throws JSONException { MockitoAnnotations.initMocks(this); - Intent intent = new Intent(); + intent = new Intent(); intent.putExtra(JsonFormConstants.JSON_FORM_KEY.JSON, DUMMY_JSON_FORM_STRING); activity = getActivityWithIntent(intent); activity.getmJSONObject().put(JsonFormConstants.SKIP_BLANK_STEPS, true); - - Assert.assertNotNull(activity); + Application application = Mockito.spy(Application.class); + Mockito.doReturn(context).when(application).getApplicationContext(); } @Test @@ -423,12 +430,13 @@ public void testRefreshExpansionPanelShouldInvokeExpectedMethods() throws JSONEx Mockito.verify(mockUtils) .enableExpansionPanelViews(ArgumentMatchers.eq(linearLayout)); } + @Test public void testGetRelevanceAddressReturnsExpectedAddressAndRelevancePair() throws JSONException { View view = new View(activity.getBaseContext()); JSONObject curRelevance = new JSONObject(); try { - curRelevance = new JSONObject("{ex-checkbox:[{\"or\":[\"other\"]}]}}"); + curRelevance = new JSONObject("{ex-checkbox:[{\"or\":[\"other\"]}]}}"); } catch (JSONException e) { e.printStackTrace(); } @@ -451,4 +459,163 @@ public void testGetRelevanceAddressReturnsExpectedAddressAndRelevancePair() thro } + @Test + public void testGetValueFromAddressReturnsNull() throws Exception { + String[] address = {"address1:one", "address2:two", "address3:three"}; + JSONObject jsonObject = Mockito.mock(JSONObject.class); + activity = new JsonFormActivity(); + Facts facts = Whitebox.invokeMethod(activity, "getValueFromAddress", address, true, jsonObject); + assertEquals(0, facts.asMap().size()); + + } + + + @Test + public void testUpdateUiByCalculationReturnsNullPair() throws JSONException { + activity = getActivityWithIntent(intent); + int id = ViewUtil.generateViewId(); + String calculation = "{\"user_last_name\":" + new JSONObject("{\"user_last_name\":\"button\"}") + "}:user_last_name"; + MaterialEditText view = Mockito.spy(new MaterialEditText(activity.getApplicationContext())); + view.setId(id); + view.setTag(R.id.calculation, calculation); + view.setTag(R.id.key, "form_key"); + view.setTag(R.id.address, "step1:user_last_name"); + Pair pair = activity.getCalculationAddressAndValue(view); + assertEquals(null, pair.first); + } + + @Test + public void testUpdateUIByMaterialEditText() throws Exception { + View view = Mockito.mock(MaterialEditText.class); + String address = "test:key"; + String childKey = "test"; + String previous = ""; + String errorMessage = "false"; + String key = "yes"; + Mockito.doReturn(address).when(view).getTag(R.id.address); + Mockito.doReturn(childKey).when(view).getTag(R.id.childKey); + Mockito.doReturn(previous).when(view).getTag(R.id.previous); + Mockito.doReturn(key).when(view).getTag(R.id.key); + Mockito.doReturn("edit_text").when(view).getTag(R.id.type); + String json = " {\n" + + " \"key\": \"user_first_name\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"\",\n" + + " \"openmrs_entity_id\": \"\",\n" + + " \"type\": \"edit_text\",\n" + + " \"hint\": \"User First name\",\n" + + " \"edit_type\": \"name\",\n" + + " \"v_required\": {\n" + + " \"value\": \"true\",\n" + + " \"err\": \"Please enter the first name\"\n" + + " },\n" + + " \"v_regex\": {\n" + + " \"value\": \"[A-Za-z\\\\s\\\\.\\\\-]*\",\n" + + " \"err\": \"Please enter a valid name\"\n" + + " }\n" + + " }"; + Mockito.doReturn(new JSONObject(json)).when(view).getTag(R.id.json_object); + Whitebox.invokeMethod(activity, "updateUiByConstraints", view, true, errorMessage); + view.getTag(R.id.key); + assertEquals("yes", view.getTag(R.id.key)); + + + } + + @Test + public void testUpdateUIByConstraintsOfLinearLayoutReturnsNull() throws Exception { + View view = Mockito.mock(LinearLayout.class); + String address = "test:key"; + String childKey = "test"; + String previous = ""; + String errorMessage = "false"; + String key = "yes"; + Mockito.doReturn(address).when(view).getTag(R.id.address); + Mockito.doReturn(childKey).when(view).getTag(R.id.childKey); + Mockito.doReturn(previous).when(view).getTag(R.id.previous); + Mockito.doReturn(key).when(view).getTag(R.id.key); + Mockito.doReturn("linear_layout").when(view).getTag(R.id.type); + String json = " {\n" + + " \"key\": \"user_check_box\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"\",\n" + + " \"openmrs_entity_id\": \"\",\n" + + " \"openmrs_data_type\": \"select one\",\n" + + " \"type\": \"check_box\",\n" + + " \"label\": \"Do want to select any checkbox?\",\n" + + " \"label_text_style\": \"bold\",\n" + + " \"options\": [\n" + + " {\n" + + " \"key\": \"None\",\n" + + " \"text\": \"None\",\n" + + " \"value\": false,\n" + + " \"openmrs_choice_id\": \"\"\n" + + " },\n" + + " {\n" + + " \"key\": \"yes\",\n" + + " \"text\": \"Yes\",\n" + + " \"value\": false,\n" + + " \"openmrs_choice_id\": \"\"\n" + + " },\n" + + " {\n" + + " \"key\": \"no\",\n" + + " \"text\": \"No\",\n" + + " \"value\": false,\n" + + " \"openmrs_choice_id\": \"\"\n" + + " },\n" + + " {\n" + + " \"key\": \"other\",\n" + + " \"text\": \"Other\",\n" + + " \"value\": false,\n" + + " \"openmrs_choice_id\": \"\"\n" + + " }\n" + + " ],\n" + + " \"v_required\": {\n" + + " \"value\": \"false\"\n" + + " },\n" + + " \"value\": \"[yes]\"\n" + + " }"; + Mockito.doReturn(new JSONObject(json)).when(view).getTag(R.id.json_object); + Whitebox.invokeMethod(activity, "updateUiByConstraints", view, true, errorMessage); + LinearLayout linearLayout = (LinearLayout) view; + assertEquals(null, linearLayout.getChildAt(0)); + } + + @Test + public void testUpdateUIByConstraintsOfRadioButton() throws Exception { + View view = Mockito.mock(RadioGroup.class); + String address = "test:key"; + String childKey = "test"; + String previous = "false"; + String errorMessage = "false"; + String key = "yes"; + Mockito.doReturn(address).when(view).getTag(R.id.address); + Mockito.doReturn(childKey).when(view).getTag(R.id.childKey); + Mockito.doReturn(previous).when(view).getTag(R.id.previous); + Mockito.doReturn(key).when(view).getTag(R.id.key); + Mockito.doReturn("check_box").when(view).getTag(R.id.type); + String json = " {\n" + + " \"key\": \"respiratory_exam_radio_button\",\n" + + " \"type\": \"native_radio\",\n" + + " \"values\": [\n" + + " \"3:Abnormal\"\n" + + " ]\n" + + " }"; + Mockito.doReturn(new JSONObject(json)).when(view).getTag(R.id.json_object); + Whitebox.invokeMethod(activity, "updateUiByConstraints", view, true, errorMessage); + assertEquals(key, view.getTag(R.id.key)); + } + + @Test + public void testGetViewKey() throws Exception { + View view = Mockito.mock(View.class); + String key = "key"; + String childKey = "childKey"; + JsonFormActivity jsonFormActivity = Mockito.mock(JsonFormActivity.class); + Mockito.doReturn(childKey).when(view).getTag(R.id.childKey); + Mockito.doReturn(key).when(view).getTag(R.id.key); + String returnKey = Whitebox.invokeMethod(jsonFormActivity, "getViewKey", view); + assertEquals(key + ":" + childKey, returnKey); + + } } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/ExpansionPanelGenericPopUpDialogTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/ExpansionPanelGenericPopUpDialogTest.java new file mode 100644 index 000000000..8073d2eca --- /dev/null +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/ExpansionPanelGenericPopUpDialogTest.java @@ -0,0 +1,51 @@ +package com.vijay.jsonwizard.customviews; + +import com.vijay.jsonwizard.BaseTest; +import com.vijay.jsonwizard.customviews.ExpansionPanelGenericPopupDialog; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +@RunWith(PowerMockRunner.class) +public class ExpansionPanelGenericPopUpDialogTest extends BaseTest { + private final String theAccordion = "{\n" + + " \"title\": \"Expansion Panel\",\n" + + " \"fields\": [\n" + + " {\n" + + " \"key\": \"accordion_panel_demo\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"\",\n" + + " \"openmrs_entity_id\": \"\",\n" + + " \"text\": \"Expansion Panel Demo\",\n" + + " \"type\": \"expansion_panel\",\n" + + " \"content_form\": \"expansion_panel_sub_form\",\n" + + " \"container\": \"anc_test\"\n" + + " }\n" + + " ]\n" + + " }"; + @Mock + private ExpansionPanelGenericPopupDialog expansionPanelGenericPopupDialog; + + @Before + public void setUp() { + expansionPanelGenericPopupDialog = Mockito.mock(ExpansionPanelGenericPopupDialog.class); + + } + + @Test + public void testAddRequiredFields() throws Exception { + JSONArray jsonArray = new JSONObject(theAccordion).getJSONArray("fields"); + Mockito.doReturn(jsonArray).when(expansionPanelGenericPopupDialog).getSubFormsFields(); + Whitebox.invokeMethod(expansionPanelGenericPopupDialog, "addRequiredFields", new JSONObject(theAccordion)); + Assert.assertEquals(1,expansionPanelGenericPopupDialog.getSubFormsFields().length()); + + } +} diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/NumericDatePickerTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/NumericDatePickerTest.java index 9ec55bde4..8d7f8c11b 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/NumericDatePickerTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/customviews/NumericDatePickerTest.java @@ -140,7 +140,6 @@ public void testNumericDatePickerSetMinValueLimitsCorrectly() { //Try set a date within min LocalDate dateFiveMonthsBeforeToday = localDate.minusMonths(6); datePicker.setDate(dateFiveMonthsBeforeToday.toDate()); - Assert.assertEquals(localDate.getDayOfMonth(), datePicker.getDayOfMonth()); Assert.assertEquals(dateFiveMonthsBeforeToday.getMonthOfYear() - 1, datePicker.getMonth()); Assert.assertEquals(dateFiveMonthsBeforeToday.getYear(), datePicker.getYear()); diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterRoboElectricTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterRoboElectricTest.java index 3164410c7..b4f4d4b17 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterRoboElectricTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterRoboElectricTest.java @@ -1,12 +1,42 @@ package com.vijay.jsonwizard.presenters; +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; +import static android.os.Looper.getMainLooper; +import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP1; +import static com.vijay.jsonwizard.presenters.JsonFormFragmentPresenter.RESULT_LOAD_IMG; +import static com.vijay.jsonwizard.utils.PermissionUtils.CAMERA_PERMISSION_REQUEST_CODE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.only; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; +import static org.robolectric.annotation.LooperMode.Mode.PAUSED; + import android.Manifest.permission; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import androidx.appcompat.widget.AppCompatSpinner; import android.view.MenuItem; import android.view.View; import android.widget.CheckBox; @@ -15,6 +45,8 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.appcompat.widget.AppCompatSpinner; + import com.vijay.jsonwizard.BaseTest; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.TestConstants; @@ -24,7 +56,6 @@ import com.vijay.jsonwizard.fragments.JsonFormFragment; import com.vijay.jsonwizard.fragments.JsonWizardFormFragment; import com.vijay.jsonwizard.interactors.JsonFormInteractor; -import com.vijay.jsonwizard.interfaces.CommonListener; import com.vijay.jsonwizard.interfaces.OnFieldsInvalid; import com.vijay.jsonwizard.rules.RulesEngineFactory; import com.vijay.jsonwizard.shadow.ShadowContextCompat; @@ -62,37 +93,6 @@ import java.util.List; import java.util.Stack; -import static android.app.Activity.RESULT_CANCELED; -import static android.app.Activity.RESULT_OK; -import static android.os.Looper.getMainLooper; -import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP1; -import static com.vijay.jsonwizard.presenters.JsonFormFragmentPresenter.RESULT_LOAD_IMG; -import static com.vijay.jsonwizard.utils.PermissionUtils.CAMERA_PERMISSION_REQUEST_CODE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.only; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.robolectric.Shadows.shadowOf; -import static org.robolectric.annotation.LooperMode.Mode.PAUSED; - /** * Created by samuelgithengi on 3/3/20. */ @@ -730,9 +730,10 @@ public void testOnSpinnerEditBtnClickShouldResetWidgetReadOnly() throws JSONExce } @Test - public void testCleanUp(){ + public void testCleanUp() { presenter.cleanUp(); boolean cleanUpAndExit = Whitebox.getInternalState(presenter, "cleanupAndExit"); assertTrue(cleanUpAndExit); } + } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterTest.java index ec5940187..7deacb747 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonFormFragmentPresenterTest.java @@ -1,8 +1,20 @@ package com.vijay.jsonwizard.presenters; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.verifyStatic; +import static org.powermock.api.mockito.PowerMockito.when; + import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.fragments.JsonFormFragment; import com.vijay.jsonwizard.interfaces.JsonApi; +import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.views.JsonFormFragmentView; import com.vijay.jsonwizard.widgets.CountDownTimerFactory; @@ -13,21 +25,14 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.verifyStatic; -import static org.powermock.api.mockito.PowerMockito.when; +import java.util.concurrent.Executor; /** * Created by Vincent Karuri on 18/02/2020 @@ -42,11 +47,18 @@ public class JsonFormFragmentPresenterTest { @Mock private JsonFormFragment jsonFormFragment; + @Mock + private AppExecutors appExecutors; + + Executor executor; + @Before public void setUp() throws JSONException { MockitoAnnotations.initMocks(this); setUpJsonFormFragment(true); jsonFormFragmentPresenter = new JsonFormFragmentPresenter(jsonFormFragment); + executor = mock(Executor.class); + appExecutors = mock(AppExecutors.class); } @Test @@ -76,7 +88,15 @@ public void testMoveToNextStepShouldMoveToNextStepIfExists() throws Exception { } @Test - public void testCheckAndStopCountdownAlarmShouldStopAlarm() throws JSONException { + public void testCheckAndStopCountdownAlarmShouldStopAlarm() throws JSONException, InterruptedException { + Mockito.doAnswer((Answer) invocation -> { + Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + }).when(executor).execute(Mockito.any(Runnable.class)); + Mockito.when(jsonFormFragment.getJsonApi().getAppExecutors()).thenReturn(appExecutors); + Mockito.when(appExecutors.diskIO()).thenReturn(executor); + Thread.sleep(1000); bootStrapCurrentJsonState(); mockStatic(CountDownTimerFactory.class); jsonFormFragmentPresenter.checkAndStopCountdownAlarm(); diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterRoboelectricTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterRoboelectricTest.java index d56012b52..2c0bb07ee 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterRoboelectricTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterRoboelectricTest.java @@ -24,6 +24,7 @@ import com.vijay.jsonwizard.shadow.ShadowFileProvider; import com.vijay.jsonwizard.shadow.ShadowIntent; import com.vijay.jsonwizard.shadow.ShadowPermissionUtils; +import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.views.CustomTextView; import com.vijay.jsonwizard.widgets.NativeRadioButtonFactory; @@ -34,17 +35,21 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.io.File; import java.util.UUID; +import java.util.concurrent.Executor; import static com.vijay.jsonwizard.presenters.JsonFormFragmentPresenter.RESULT_LOAD_IMG; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -69,6 +74,11 @@ public class JsonWizardFormFragmentPresenterRoboelectricTest extends BaseTest { @Mock private PackageManager packageManager; + @Mock + private AppExecutors appExecutors; + + Executor executor; + @Captor private ArgumentCaptor intentArgumentCaptor; @@ -78,6 +88,8 @@ public class JsonWizardFormFragmentPresenterRoboelectricTest extends BaseTest { @Before public void setUp() throws JSONException { + executor = mock(Executor.class); + appExecutors = mock(AppExecutors.class); when(formFragment.getJsonApi()).thenReturn(formActivity); when(formFragment.getOnFieldsInvalidCallback()).thenReturn(onFieldsInvalid); when(formActivity.getmJSONObject()).thenReturn(new JSONObject(TestConstants.BASIC_FORM)); @@ -87,7 +99,16 @@ public void setUp() throws JSONException { } @Test - public void testOnNextClickShouldMoveToNextStep() throws JSONException { + public void testOnNextClickShouldMoveToNextStep() throws JSONException, InterruptedException { + Mockito.doAnswer((Answer) invocation -> { + Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + }).when(executor).execute(Mockito.any(Runnable.class)); + when(formFragment.getJsonApi().getAppExecutors()).thenReturn(appExecutors); + when(appExecutors.diskIO()).thenReturn(executor); + Thread.sleep(1000); + when(formActivity.nextStep()).thenReturn("step2"); formFragmentPresenter.onNextClick(null); verify(jsonFormInteractor).fetchFormElements("step2", formFragment, formActivity.getmJSONObject().getJSONObject("step2"), null, false); diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterTest.java index a87eceda9..2f812c41f 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/presenters/JsonWizardFormFragmentPresenterTest.java @@ -9,6 +9,7 @@ import com.vijay.jsonwizard.interactors.JsonFormInteractor; import com.vijay.jsonwizard.interfaces.JsonApi; import com.vijay.jsonwizard.interfaces.OnFieldsInvalid; +import com.vijay.jsonwizard.utils.AppExecutors; import com.vijay.jsonwizard.utils.ValidationStatus; import org.json.JSONException; @@ -19,6 +20,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -27,6 +29,7 @@ import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Executor; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -35,6 +38,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; @RunWith(PowerMockRunner.class) @@ -64,6 +68,11 @@ public class JsonWizardFormFragmentPresenterTest { @Mock private Resources resources; + @Mock + private AppExecutors appExecutors; + + Executor executor; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -78,10 +87,22 @@ public void setUp() { Whitebox.setInternalState(presenter, "viewRef", new WeakReference<>(formFragment)); doReturn("step1").when(mStepDetails).optString(anyString()); Whitebox.setInternalState(presenter, "mStepDetails", mStepDetails); + executor = mock(Executor.class); + appExecutors = mock(AppExecutors.class); } @Test - public void testOnNextClickShouldPerformCorrectAction() throws JSONException { + public void testOnNextClickShouldPerformCorrectAction() throws JSONException, InterruptedException { + + Mockito.doAnswer((Answer) invocation -> { + Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + }).when(executor).execute(Mockito.any(Runnable.class)); + when(formFragment.getJsonApi().getAppExecutors()).thenReturn(appExecutors); + when(appExecutors.diskIO()).thenReturn(executor); + Thread.sleep(1000); + mockStatic(JsonWizardFormFragment.class); PowerMockito.when(JsonWizardFormFragment.getFormFragment(anyString())).thenReturn(formFragment); @@ -89,8 +110,10 @@ public void testOnNextClickShouldPerformCorrectAction() throws JSONException { // when no incorrectly formatted fields mJsonObject.put(JsonFormConstants.VALIDATE_ON_SUBMIT, true); presenter.onNextClick(mock(LinearLayout.class)); + verifyMovesToNextStep(1); + // when form is valid mJsonObject.put(JsonFormConstants.VALIDATE_ON_SUBMIT, false); presenter.onNextClick(mock(LinearLayout.class)); diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/rules/RulesEngineHelperTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/rules/RulesEngineHelperTest.java index a6e8608fa..ce47692fc 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/rules/RulesEngineHelperTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/rules/RulesEngineHelperTest.java @@ -1,26 +1,34 @@ package com.vijay.jsonwizard.rules; +import static org.junit.Assert.assertEquals; + import com.vijay.jsonwizard.BaseTest; import com.vijay.jsonwizard.shadow.ShadowRulesEngineDateUtil; +import org.junit.Before; import org.junit.Test; import org.robolectric.annotation.Config; +import java.time.LocalDate; +import java.time.Period; import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertEquals; - /** * Created by samuelgithengi on 3/7/19. */ public class RulesEngineHelperTest extends BaseTest { public static String TEST_DATE_TIME = "2020-05-30T10:15:30Z"; + private RulesEngineHelper helper; + + @Before + public void setUp() { + helper = new RulesEngineHelper(); + } @Test public void testIfNull() { - RulesEngineHelper helper = new RulesEngineHelper(); assertEquals("0", helper.ifNull(null, "0")); assertEquals("1", helper.ifNull("", "1")); assertEquals("123", helper.ifNull("123", "")); @@ -30,7 +38,6 @@ public void testIfNull() { @Test @Config(shadows = {ShadowRulesEngineDateUtil.class}) public void getDateTimeTodayReturnsExpectedDateTime() { - RulesEngineHelper helper = new RulesEngineHelper(); assertEquals(new RulesEngineDateUtil().getDateTimeToday(), helper.getDateTimeToday()); } @@ -44,10 +51,29 @@ public void getDateTodayReturnsExpectedDate() { @Test public void canGetNonNullValueFromList() { List stringList = new ArrayList<>(); - RulesEngineHelper helper = new RulesEngineHelper(); stringList.add("Hello"); stringList.add(""); assertEquals("Hello", helper.getNonBlankValue(stringList)); } + @Test + public void testGetMothersAge() { + String dob = "04-07-1990"; + String[] dobArray = dob.split("-"); + LocalDate localDate = LocalDate.of(Integer.parseInt(dobArray[2]), Integer.parseInt(dobArray[1]), Integer.parseInt(dobArray[0])); + int expectedAge = Period.between(localDate, LocalDate.now()).getYears(); + int actualAge = helper.getMothersAge(dob); + assertEquals(expectedAge, actualAge); + } + + @Test + public void testGetDifferenceDays() { + String dateString1 = "04-07-1990"; + String dateString2 = "06-08-1990"; + Long expectedDays = Long.parseLong("33"); + Long actualDays = helper.getDifferenceDays(dateString2, dateString1); + assertEquals(expectedDays, actualDays); + + } + } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/FormUtilsTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/FormUtilsTest.java index d7c31aa8b..538fd6114 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/FormUtilsTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/FormUtilsTest.java @@ -112,8 +112,8 @@ public class FormUtilsTest extends BaseTest { " },\n" + " \"value\": \"user_one\"\n" + " }"; + private final String jsonForm = "{\"count\":\"4\",\"encounter_type\":\"Test\",\"entity_id\":\"\",\"relational_id\":\"\",\"validate_on_submit\":true,\"show_errors_on_submit\":true,\"metadata\":{\"start\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"start\",\"openmrs_entity_id\":\"163137AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"end\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"end\",\"openmrs_entity_id\":\"163138AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"today\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"encounter\",\"openmrs_entity_id\":\"encounter_date\"},\"deviceid\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"deviceid\",\"openmrs_entity_id\":\"163149AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"subscriberid\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"subscriberid\",\"openmrs_entity_id\":\"163150AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"simserial\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"simserial\",\"openmrs_entity_id\":\"163151AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"phonenumber\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"phonenumber\",\"openmrs_entity_id\":\"163152AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"encounter_location\":\"\",\"look_up\":{\"entity_id\":\"\",\"value\":\"\"}},\"step1\":{\"title\":\"Test\",\"next\":\"step2\",\"fields\":[{\"key\":\"delivery_complications\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"161641AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"openmrs_data_type\":\"select one\",\"type\":\"check_box\",\"label\":\"Any delivery complications?\",\"label_text_size\":\"18sp\",\"label_text_color\":\"#FF9800\",\"hint\":\"Any delivery complications?\",\"read_only\":true,\"editable\":true,\"exclusive\":[\"none\"],\"options\":[{\"key\":\"none\",\"text\":\"None\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"severe_bleeding\",\"text\":\"Severe bleeding/Hemorrhage\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_color\":\"#000000\"},{\"key\":\"placenta_previa\",\"text\":\"Placenta previa\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_size\":\"15sp\"},{\"key\":\"cord_prolapse\",\"text\":\"Cord prolapse\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_size\":\"10sp\"},{\"key\":\"prolonged_obstructed_labour\",\"text\":\"Prolonged/obstructed labour\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"abnormal_presentation\",\"text\":\"Abnormal presentation\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_color\":\"#FF9800\"},{\"key\":\"perineal_tear\",\"text\":\"Perineal tear (2, 3 or 4th degree)\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"Other\",\"text\":\"Other\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}],\"v_required\":{\"value\":\"false\"}},{\"key\":\"first_name\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"person\",\"openmrs_entity_id\":\"first_name\",\"type\":\"edit_text\",\"hidden\":true,\"hint\":\"First name\",\"edit_type\":\"name\",\"v_required\":{\"value\":\"true\",\"err\":\"Please enter the first name\"},\"v_regex\":{\"value\":\"[A-Za-z\\\\s\\\\.\\\\-]*\",\"err\":\"Please enter a valid name\"},\"calculation\":{\"rules-engine\":{\"ex-rules\":{\"rules-file\":\"sample-calculation-rules.yml\"}}}}]},\"step2\":{\"title\":\"Test 2\",\"next\":\"step3\",\"fields\":[{\"key\":\"fetal_heartbeat\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"type\":\"native_radio\",\"label\":\"Which medications is she still taking ? Which medications is she still taking ?\",\"label_text_style\":\"bold\",\"text_color\":\"#000000\",\"extra_rel\":true,\"has_extra_rel\":\"yes\",\"options\":[{\"key\":\"yes\",\"text\":\"Yes\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"specify fetal heart rate (bpm)...\",\"specify_widget\":\"normal_edit_text\",\"specify_info_color\":\"#8C8C8C\",\"secondary_suffix\":\"bpm\",\"content_form\":\"fetal_heartbeat_sub_form\"},{\"key\":\"no\",\"text\":\"No\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"specify fetal heart rate (bpm)...\",\"specify_widget\":\"check_box\",\"specify_info_color\":\"#8C8C8C\",\"content_form\":\"fetal_heartbeat_sub_form\"}],\"v_required\":{\"value\":true,\"err\":\"Please specify if fetal heartbeat is present.\"}},{\"key\":\"fetal_heart_beat_rate_value\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"type\":\"normal_edit_text\",\"edit_text_style\":\"bordered\",\"edit_type\":\"number\"}]},\"step3\":{\"title\":\"Maternal Exam\",\"next\":\"step4\",\"fields\":[{\"key\":\"spacer\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"spacer\",\"type\":\"spacer\",\"spacer_height\":\"20dp\"},{\"key\":\"gravida_label\",\"type\":\"label\",\"label_text_style\":\"bold\",\"text\":\"No. of pregnancies (including this pregnancy)\",\"text_color\":\"#000000\",\"v_required\":{\"value\":true}}]}}"; - private String jsonForm = "{\"count\":\"4\",\"encounter_type\":\"Test\",\"entity_id\":\"\",\"relational_id\":\"\",\"validate_on_submit\":true,\"show_errors_on_submit\":true,\"metadata\":{\"start\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"start\",\"openmrs_entity_id\":\"163137AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"end\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"end\",\"openmrs_entity_id\":\"163138AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"today\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"encounter\",\"openmrs_entity_id\":\"encounter_date\"},\"deviceid\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"deviceid\",\"openmrs_entity_id\":\"163149AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"subscriberid\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"subscriberid\",\"openmrs_entity_id\":\"163150AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"simserial\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"simserial\",\"openmrs_entity_id\":\"163151AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"phonenumber\":{\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_data_type\":\"phonenumber\",\"openmrs_entity_id\":\"163152AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},\"encounter_location\":\"\",\"look_up\":{\"entity_id\":\"\",\"value\":\"\"}},\"step1\":{\"title\":\"Test\",\"next\":\"step2\",\"fields\":[{\"key\":\"delivery_complications\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"161641AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"openmrs_data_type\":\"select one\",\"type\":\"check_box\",\"label\":\"Any delivery complications?\",\"label_text_size\":\"18sp\",\"label_text_color\":\"#FF9800\",\"hint\":\"Any delivery complications?\",\"read_only\":true,\"editable\":true,\"exclusive\":[\"none\"],\"options\":[{\"key\":\"none\",\"text\":\"None\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"severe_bleeding\",\"text\":\"Severe bleeding/Hemorrhage\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_color\":\"#000000\"},{\"key\":\"placenta_previa\",\"text\":\"Placenta previa\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_size\":\"15sp\"},{\"key\":\"cord_prolapse\",\"text\":\"Cord prolapse\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_size\":\"10sp\"},{\"key\":\"prolonged_obstructed_labour\",\"text\":\"Prolonged/obstructed labour\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"abnormal_presentation\",\"text\":\"Abnormal presentation\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"text_color\":\"#FF9800\"},{\"key\":\"perineal_tear\",\"text\":\"Perineal tear (2, 3 or 4th degree)\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"Other\",\"text\":\"Other\",\"value\":false,\"openmrs_choice_id\":\"160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}],\"v_required\":{\"value\":\"false\"}},{\"key\":\"first_name\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"person\",\"openmrs_entity_id\":\"first_name\",\"type\":\"edit_text\",\"hidden\":true,\"hint\":\"First name\",\"edit_type\":\"name\",\"v_required\":{\"value\":\"true\",\"err\":\"Please enter the first name\"},\"v_regex\":{\"value\":\"[A-Za-z\\\\s\\\\.\\\\-]*\",\"err\":\"Please enter a valid name\"},\"calculation\":{\"rules-engine\":{\"ex-rules\":{\"rules-file\":\"sample-calculation-rules.yml\"}}}}]},\"step2\":{\"title\":\"Test 2\",\"next\":\"step3\",\"fields\":[{\"key\":\"fetal_heartbeat\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"type\":\"native_radio\",\"label\":\"Which medications is she still taking ? Which medications is she still taking ?\",\"label_text_style\":\"bold\",\"text_color\":\"#000000\",\"extra_rel\":true,\"has_extra_rel\":\"yes\",\"options\":[{\"key\":\"yes\",\"text\":\"Yes\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"specify fetal heart rate (bpm)...\",\"specify_widget\":\"normal_edit_text\",\"specify_info_color\":\"#8C8C8C\",\"secondary_suffix\":\"bpm\",\"content_form\":\"fetal_heartbeat_sub_form\"},{\"key\":\"no\",\"text\":\"No\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"specify fetal heart rate (bpm)...\",\"specify_widget\":\"check_box\",\"specify_info_color\":\"#8C8C8C\",\"content_form\":\"fetal_heartbeat_sub_form\"}],\"v_required\":{\"value\":true,\"err\":\"Please specify if fetal heartbeat is present.\"}},{\"key\":\"fetal_heart_beat_rate_value\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"type\":\"normal_edit_text\",\"edit_text_style\":\"bordered\",\"edit_type\":\"number\"}]},\"step3\":{\"title\":\"Maternal Exam\",\"next\":\"step4\",\"fields\":[{\"key\":\"spacer\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"spacer\",\"type\":\"spacer\",\"spacer_height\":\"20dp\"},{\"key\":\"gravida_label\",\"type\":\"label\",\"label_text_style\":\"bold\",\"text\":\"No. of pregnancies (including this pregnancy)\",\"text_color\":\"#000000\",\"v_required\":{\"value\":true}}]}}"; @Before public void setUp() throws JSONException { @@ -716,13 +716,13 @@ public void testShowGenericDialogShouldInvokeExpectedMethods() { Mockito.verify(mainLayout, Mockito.only()).clearFocus(); Mockito.verify(mockFragmentTransaction).add(ArgumentMatchers.any(DialogFragment.class), ArgumentMatchers.eq("GenericPopup")); } - + @Test public void testGetDynamicLabelInfoList() throws JSONException { JSONArray jsonArray = new JSONArray("[{\"dynamic_label_title\": \"sample title\",\"dynamic_label_text\": \"sample text\",\"dynamic_label_image_src\": \"img/img.png\"}]"); ArrayList expectedList = new ArrayList<>(); expectedList.add(new DynamicLabelInfo("sample title", "sample text", "img/img.png")); - ArrayList actualList = FormUtils.getDynamicLabelInfoList(jsonArray); + ArrayList actualList = FormUtils.getDynamicLabelInfoList(jsonArray); Assert.assertEquals(expectedList.get(0).getDynamicLabelText(), actualList.get(0).getDynamicLabelText()); Assert.assertEquals(expectedList.get(0).getDynamicLabelTitle(), actualList.get(0).getDynamicLabelTitle()); Assert.assertEquals(expectedList.get(0).getDynamicLabelImageSrc(), actualList.get(0).getDynamicLabelImageSrc()); @@ -735,7 +735,6 @@ public void testCreateOptiBPDataObject() throws JSONException { Assert.assertEquals(inputJson.toString(), "{\"clientId\":\"clientId\",\"clientOpenSRPId\":\"clientOpenSRPId\"}"); } - @Test public void testSetEditModeShouldShowEditBtnAndDisableEditableView() throws JSONException { View editableView = Mockito.mock(View.class); ImageView editButton = Mockito.mock(ImageView.class); @@ -775,18 +774,22 @@ public void testSetEditModeShouldHideEditBtnAndDisableEditableViewIfReadOnlySet( } @Test - public void testSetEditModeShouldShowEditBtnAndDisableEditableViewIfEditableAndReadOnlySet() throws JSONException { - View editableView = Mockito.mock(View.class); - ImageView editButton = Mockito.mock(ImageView.class); - - JSONObject jsonObject = new JSONObject(); - jsonObject.put(JsonFormConstants.READ_ONLY, false); - jsonObject.put(JsonFormConstants.EDITABLE, false); - - FormUtils.setEditMode(jsonObject, editableView, editButton); - - Mockito.verify(editButton).setVisibility(ArgumentMatchers.eq(View.VISIBLE)); - Mockito.verify(editableView).setEnabled(ArgumentMatchers.eq(false)); + public void testUpdateValueToJsonArray() throws Exception { + FormUtils mockedFormUtils = Mockito.mock(FormUtils.class); + String item = "{\n" + + " \"key\": \"resThree3\",\n" + + " \"text\": \"Abnormal\",\n" + + " \"specify_info\": \"Specify\",\n" + + " \"specify_info_color\": \"#b5b5b5\",\n" + + " \"specify_widget\": \"check_box\",\n" + + " \"content_form\": \"child_enrollment_third_sub_form\",\n" + + " \"secondary_suffix\": \"bpm\",\n" + + " \"content_form_location\": \"\",\n" + + " \"translated_text\": \"form_strings.step1.danger_signs.danger_bleeding.text\"\n" + + "}"; + NativeFormsProperties mockedNativeProps = Mockito.mock(NativeFormsProperties.class); + Mockito.when(mockedNativeProps.isTrue(NativeFormsProperties.KEY.WIDGET_VALUE_TRANSLATED)).thenReturn(true); + Mockito.verify(mockedFormUtils, Mockito.times(0)).updateValueToJSONArray(new JSONObject(item), new JSONObject(item).optString(JsonFormConstants.VALUE)); } @Test diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/NativeFormLangUtilsTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/NativeFormLangUtilsTest.java index 849b69725..19ebc415e 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/NativeFormLangUtilsTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/NativeFormLangUtilsTest.java @@ -1,5 +1,9 @@ package com.vijay.jsonwizard.utils; +import static com.vijay.jsonwizard.utils.Utils.getTranslatedYamlFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + import android.content.Context; import android.preference.PreferenceManager; @@ -8,6 +12,8 @@ import com.vijay.jsonwizard.TestUtils; import com.vijay.jsonwizard.constants.JsonFormConstants; +import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.robolectric.RuntimeEnvironment; @@ -16,16 +22,19 @@ import java.util.Locale; import java.util.ResourceBundle; -import static com.vijay.jsonwizard.utils.Utils.getTranslatedYamlFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - /** * Created by Vincent Karuri on 20/02/2020 */ public class NativeFormLangUtilsTest extends BaseTest { private final TestUtils testUtils = new TestUtils(); + private Context context; + + @Before + public void setUp() { + context = RuntimeEnvironment.application; + + } @Test public void testJsonFormTranslationShouldTranslateForm() { @@ -98,13 +107,13 @@ public void testCanGetResourceBundleWithPropertiesFromRepository() { clientForm.setJson(enProperties); Mockito.doReturn(clientForm).when(clientFormRepository).getActiveClientFormByIdentifier(Mockito.eq("form_strings.properties")); - assertEquals("SAVE AND EXIT", NativeFormLangUtils.getResourceBundleFromRepository(RuntimeEnvironment.application, interpolatedJsonForm).getString("step1.previous_label")); + assertEquals("SAVE AND EXIT", NativeFormLangUtils.getResourceBundleFromRepository(RuntimeEnvironment.application, interpolatedJsonForm).getString("step1.previous_label")); String swProperties = "step1.title = Rekodi mpya\nstep1.previous_label = WEKA ALAFU ONDOKA"; clientForm.setJson(swProperties); NativeFormLangUtils.setAppLocale(context, "sw"); Mockito.doReturn(clientForm).when(clientFormRepository).getActiveClientFormByIdentifier(Mockito.eq("form_strings_sw.properties")); - assertEquals("Rekodi mpya", NativeFormLangUtils.getResourceBundleFromRepository(RuntimeEnvironment.application, interpolatedJsonForm).getString("step1.title")); + assertEquals("Rekodi mpya", NativeFormLangUtils.getResourceBundleFromRepository(RuntimeEnvironment.application, interpolatedJsonForm).getString("step1.title")); } @Test @@ -118,4 +127,28 @@ public void testResourceBundleWithPropertiesFromDbIsEmptyWhenClientFormDoesntExi ResourceBundle mlsResourceBundle = NativeFormLangUtils.getResourceBundleFromRepository(RuntimeEnvironment.application, interpolatedJsonForm); assertFalse(mlsResourceBundle.getKeys().hasMoreElements()); } + + @Test + public void testGetDatabaseString() { + String stringToTranslate = "form_strings.step1.danger_signs.danger_bleeding.text"; + String expectedString = "Danger Bleeding"; + Locale locale = new Locale(Locale.ENGLISH.getLanguage()); + ResourceBundle bundle = ResourceBundle.getBundle("form_strings", locale); + boolean keyIsFound = bundle.containsKey(stringToTranslate); + Assert.assertTrue(keyIsFound); + String actual = NativeFormLangUtils.translateDatabaseString(stringToTranslate, context); + assertEquals(expectedString, actual); + + } + @Test + public void testInvalidDatabaseString() { + String stringToTranslate = "form_strings.step2.danger_signs.danger_bleeding.text"; + Locale locale = new Locale(Locale.ENGLISH.getLanguage()); + ResourceBundle bundle = ResourceBundle.getBundle("form_strings", locale); + boolean keyIsFound = bundle.containsKey(stringToTranslate); + String actual = NativeFormLangUtils.translateDatabaseString(stringToTranslate, context); + assertEquals("",actual); + assertFalse(keyIsFound); + + } } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/UtilsTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/UtilsTest.java index efb3eab12..6b2a187e8 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/UtilsTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/utils/UtilsTest.java @@ -1,5 +1,9 @@ package com.vijay.jsonwizard.utils; +import static com.vijay.jsonwizard.utils.Utils.formatDateToPattern; +import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonArray; +import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonObject; + import android.app.Activity; import android.app.AlertDialog; import android.app.FragmentTransaction; @@ -49,10 +53,6 @@ import java.util.Map; import java.util.Set; -import static com.vijay.jsonwizard.utils.Utils.formatDateToPattern; -import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonArray; -import static com.vijay.jsonwizard.utils.Utils.isEmptyJsonObject; - public class UtilsTest extends BaseTest { @Mock @@ -449,9 +449,90 @@ public void testShowAlertDialogShouldDisplayAlertDialogCorrectly() { @Test public void testGetFieldKeyPrefix() { - String expectedString = "stepName#stepTitle:"; - String expectedStringWrong = "stepNamestepTitle"; - Assert.assertEquals(expectedString, Utils.getFieldKeyPrefix(JsonFormConstants.STEPNAME, "stepTitle")); - Assert.assertNotEquals(expectedStringWrong, Utils.getFieldKeyPrefix(JsonFormConstants.STEPNAME, "stepTitle")); + String expectedString = "stepName#stepTitle:"; + Assert.assertEquals(expectedString, Utils.getFieldKeyPrefix("stepName", "stepTitle")); + } + + @Test + public void testGenerateTranslatableValueWithKeyContainingOptionsField() throws Exception { + String jsonForm = "{\n" + + " \"key\": \"blood_type\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"concept\",\n" + + " \"openmrs_entity_id\": \"163126AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\n" + + " \"type\": \"native_radio\",\n" + + " \"label\": \"Blood type\",\n" + + " \"label_text_style\": \"bold\",\n" + + " \"options\": [\n" + + " {\n" + + " \"key\": \"a\",\n" + + " \"text\": \"A\",\n" + + " \"translation_text\": \"anc_profile.values.a\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"concept\",\n" + + " \"openmrs_entity_id\": \"163115AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" + + " }\n" + + " ],\n" + + " \"v_required\": {\n" + + " \"value\": true,\n" + + " \"err\": \"Please specify blood type\"\n" + + " },\n" + + " \"relevance\": {\n" + + " \"rules-engine\": {\n" + + " \"ex-rules\": {\n" + + " \"rules-file\": \"tests_relevance_rules.yml\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"index\": \"4\",\n" + + " \"value\": {\n" + + " \"value\": \"ab\",\n" + + " \"text\": \"\"\n" + + " },\n" + + " \"is_visible\": true\n" + + "}"; + String expected = " {\n" + + " \"value\":\"a\",\n" + + " \"text\":\"anc_profile.values.a\"\n" + + " }"; + JSONObject expectedJson = new JSONObject(expected); + JSONObject item = new JSONObject(jsonForm); + Assert.assertEquals(expectedJson.toString(), Utils.generateTranslatableValue(item.optJSONArray(JsonFormConstants.OPTIONS_FIELD_NAME).optJSONObject(0).optString(JsonFormConstants.KEY), item).toString()); + } + + @Test + public void testGenerateTranslatableValueWithoutOptionsField () throws Exception { + String jsonForm = + " {\n" + + " \"type\": \"native_radio\",\n" + + " \"key\": \"a\",\n" + + " \"text\": \"A\",\n" + + " \"translation_text\": \"anc_profile.values.a\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"concept\",\n" + + " \"openmrs_entity_id\": \"163115AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" + + " }"; + String expected = " {\n" + + " \"value\":\"a\",\n" + + " \"text\":\"anc_profile.values.a\"\n" + + " }"; + JSONObject expectedJson = new JSONObject(expected); + JSONObject item = new JSONObject(jsonForm); + Assert.assertEquals(expectedJson.toString(), Utils.generateTranslatableValue(item.optString(JsonFormConstants.KEY), item).toString()); + } + @Test + public void testExtractValueFromJson() throws JSONException + { + String value = JsonFormConstants.VALUE; + JSONObject object = new JSONObject(); + object.put(JsonFormConstants.VALUE, value); + + String result = Utils.extractValueFromJson(object.toString()); + Assert.assertEquals(result,JsonFormConstants.VALUE); + + String result2 = Utils.extractValueFromJson(value); + Assert.assertEquals(result2,value); + + } } -} \ No newline at end of file + diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/views/CustomTextViewTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/views/CustomTextViewTest.java new file mode 100644 index 000000000..ae09ce534 --- /dev/null +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/views/CustomTextViewTest.java @@ -0,0 +1,50 @@ +package com.vijay.jsonwizard.views; + +import android.app.Application; +import android.content.Context; +import android.graphics.Color; + +import com.vijay.jsonwizard.BaseTest; + +import org.json.JSONException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.powermock.reflect.Whitebox; +import org.robolectric.RuntimeEnvironment; + +public class CustomTextViewTest extends BaseTest { + @Mock + private Context context; + private CustomTextView customTextView; + @Mock + private CustomTextView customTextViewMock; + + @Before + public void setUp() throws JSONException { + customTextView = new CustomTextView(RuntimeEnvironment.application.getApplicationContext()); + Application application = Mockito.spy(Application.class); + MockitoAnnotations.initMocks(this); + Mockito.doReturn(context).when(application).getApplicationContext(); + Whitebox.setInternalState(customTextView, "hintOnText", true); + Mockito.doReturn(true).when(customTextViewMock).isEnabled(); + } + + @Test + public void testSetText() { + String text = "testtest"; + customTextView.setText(text); + Assert.assertEquals("testtest", customTextView.getText().toString()); + } + + @Test + public void testSetTextColor() { + customTextView = new CustomTextView(RuntimeEnvironment.application.getApplicationContext()); + int expectedTextColor = Color.parseColor("#00ff00"); + customTextView.setTextColor(expectedTextColor); + Assert.assertEquals(expectedTextColor, customTextView.getTextColors().getDefaultColor()); + } +} diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactoryTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactoryTest.java index 3dcf13126..ab6b4154c 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactoryTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/BasicRDTCaptureFactoryTest.java @@ -1,5 +1,16 @@ package com.vijay.jsonwizard.widgets; +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; +import static com.vijay.jsonwizard.constants.JsonFormConstants.RDT_CAPTURE_CODE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.robolectric.Shadows.shadowOf; +import static edu.washington.cs.ubicomplab.rdt_reader.core.Constants.SAVED_IMAGE_FILE_PATH; + import android.content.Intent; import android.content.pm.PackageManager; import android.view.View; @@ -27,17 +38,6 @@ import edu.washington.cs.ubicomplab.rdt_reader.activity.RDTCaptureActivity; -import static android.app.Activity.RESULT_CANCELED; -import static android.app.Activity.RESULT_OK; -import static com.vijay.jsonwizard.constants.JsonFormConstants.RDT_CAPTURE_CODE; -import static edu.washington.cs.ubicomplab.rdt_reader.core.Constants.SAVED_IMAGE_FILE_PATH; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.robolectric.Shadows.shadowOf; - @Config(shadows = {ShadowContextCompat.class}) public class BasicRDTCaptureFactoryTest extends FactoryTest { @@ -66,6 +66,8 @@ public void testRDTCaptureFactoryShouldCorrectlyInitializeViews() throws Excepti List viewList = basicRDTCaptureFactory.getViewsFromJson("step1", jsonFormActivity, formFragment, rdtCapture, listener, false); + WidgetArgs widgetArgs = ReflectionHelpers.getField(basicRDTCaptureFactory, "widgetArgs"); + Thread.sleep(1000); ShadowContextCompat.setPermissionStatus(1); @@ -74,7 +76,6 @@ public void testRDTCaptureFactoryShouldCorrectlyInitializeViews() throws Excepti assertEquals(1, viewList.size()); // verify widget args were populated - WidgetArgs widgetArgs = ReflectionHelpers.getField(basicRDTCaptureFactory, "widgetArgs"); assertEquals(formFragment, widgetArgs.getFormFragment()); assertEquals(listener, widgetArgs.getListener()); assertFalse(widgetArgs.isPopup()); diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/ButtonFactoryTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/ButtonFactoryTest.java index 30b86c18f..72ea4fc8b 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/ButtonFactoryTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/ButtonFactoryTest.java @@ -1,5 +1,7 @@ package com.vijay.jsonwizard.widgets; +import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP1; + import com.rey.material.widget.Button; import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.constants.JsonFormConstants; @@ -15,8 +17,6 @@ import org.mockito.Mock; import org.mockito.Mockito; -import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP1; - /** * Created by Vincent Karuri on 25/08/2020 */ diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactoryTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactoryTest.java index cd38953af..9ea6825d5 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactoryTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/NativeRadioButtonFactoryTest.java @@ -1,9 +1,15 @@ package com.vijay.jsonwizard.widgets; +import android.app.Activity; +import android.app.FragmentManager; import android.view.View; +import android.widget.RadioButton; + import com.vijay.jsonwizard.BaseTest; +import com.vijay.jsonwizard.R; import com.vijay.jsonwizard.activities.JsonFormActivity; +import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.fragments.JsonFormFragment; import com.vijay.jsonwizard.interfaces.CommonListener; import com.vijay.jsonwizard.utils.FormUtils; @@ -18,6 +24,7 @@ import org.mockito.MockitoAnnotations; import org.powermock.reflect.Whitebox; import org.robolectric.Robolectric; +import org.robolectric.shadows.ShadowLooper; import java.util.List; import java.util.Set; @@ -30,6 +37,10 @@ public class NativeRadioButtonFactoryTest extends BaseTest { private JsonFormFragment formFragment; @Mock private CommonListener listener; + @Mock + private RadioButton radioButton; + + private Activity activity; @Before public void setUp() { @@ -37,6 +48,7 @@ public void setUp() { factory = new NativeRadioButtonFactory(); formUtils = new FormUtils(); jsonFormActivity = Robolectric.buildActivity(JsonFormActivity.class, getJsonFormActivityIntent()).create().get(); + activity = Mockito.spy(Activity.class); } @Test @@ -44,7 +56,6 @@ public void testNativeRadioButtonFactoryInstantiatesViewsCorrectly() throws Exce String nativeRadioButtonString = "{\"key\":\"respiratory_exam\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"165367AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"type\":\"native_radio\",\"label\":\"Respiratory exam\",\"label_text_style\":\"bold\",\"text_color\":\"#000000\",\"extra_rel\":true,\"has_extra_rel\":\"3\",\"options\":[{\"key\":\"1\",\"text\":\"Not done\",\"openmrs_entity_parent\":\"165367AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"1118AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"2\",\"text\":\"Normal\",\"openmrs_entity_parent\":\"165367AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"1115AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"},{\"key\":\"3\",\"text\":\"Abnormal\",\"specify_info\":\"User sub specify...\",\"specify_widget\":\"normal_edit_text\",\"specify_info_color\":\"#8C8C8C\",\"secondary_suffix\":\"bpm\",\"extra_info\":\"Here we go\",\"content_form\":\"user_native_sub_form\",\"secondary_value\":[{\"key\":\"yes\",\"type\":\"date_picker\",\"values\":[\"24-09-2020\"]}],\"openmrs_entity_parent\":\"165367AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\",\"openmrs_entity\":\"concept\",\"openmrs_entity_id\":\"1116AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}],\"value\":\"3\",\"v_required\":{\"value\":true,\"err\":\"Please enter the child's home facility\"},\"read_only\":true,\"editable\":true,\"relevance\":{\"rules-engine\":{\"ex-rules\":{\"rules-file\":\"tree_relevance_rules.yml\"}}},\"constraints\":{\"rules-engine\":{\"ex-rules\":{\"rules-file\":\"tree_constraints_rules.yml\"}}},\"calculation\":{\"rules-engine\":{\"ex-rules\":{\"rules-file\":\"tree_calculation_rules.yml\"}}}}"; JSONObject nativeRadioButtonObject = new JSONObject(nativeRadioButtonString); Assert.assertNotNull(nativeRadioButtonString); - Assert.assertNotNull(formUtils); FormUtils formUtilsSpy = Mockito.spy(formUtils); Assert.assertNotNull(formUtilsSpy); @@ -98,7 +109,11 @@ public void testGetSecondaryDateValueWithEmptyValues() throws Exception { public void testGetOptionTextWithSecondaryValue() throws Exception { JSONObject jsonObject = new JSONObject("{\"key\":\"user_sub_form\",\"openmrs_entity_parent\":\"\",\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"type\":\"native_radio\",\"label\":\"User sub forms?\",\"label_text_style\":\"bold\",\"text_color\":\"#000000\",\"extra_rel\":true,\"has_extra_rel\":\"yes\",\"options\":[{\"key\":\"yes\",\"text\":\"Yes\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"User sub specify...\",\"specify_widget\":\"normal_edit_text\",\"specify_info_color\":\"#8C8C8C\",\"secondary_suffix\":\"bpm\",\"content_form\":\"user_native_sub_form\",\"secondary_value\":[{\"key\":\"yes\",\"type\":\"date_picker\",\"values\":[\"24-09-2020\"]}]},{\"key\":\"no\",\"text\":\"No\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\"}],\"value\":\"yes\",\"v_required\":{\"value\":true,\"err\":\"Please specify user native form.\"}}"); JSONObject item = new JSONObject("{\"key\":\"yes\",\"text\":\"Yes\",\"value\":false,\"openmrs_entity\":\"\",\"openmrs_entity_id\":\"\",\"specify_info\":\"User sub specify...\",\"specify_widget\":\"normal_edit_text\",\"specify_info_color\":\"#8C8C8C\",\"secondary_suffix\":\"bpm\",\"content_form\":\"user_native_sub_form\",\"secondary_value\":[{\"key\":\"yes\",\"type\":\"date_picker\",\"values\":[\"24-09-2020\"]}]}"); + JSONObject valueObject = new JSONObject(); + valueObject.put(JsonFormConstants.VALUE,"yes"); + valueObject.put(JsonFormConstants.TEXT,""); + jsonObject.put(JsonFormConstants.VALUE, valueObject); String optionText = Whitebox.invokeMethod(new NativeRadioButtonFactory(), "getOptionTextWithSecondaryValue", item, jsonObject); Assert.assertEquals("Yes:24-09-2020", optionText); } @@ -117,4 +132,67 @@ public void testGetCustomTranslatableWidgetFields() { Assert.assertEquals(4, editableProperties.size()); Assert.assertEquals("options.text", editableProperties.iterator().next()); } + + @Test + public void testSelectedButton() throws Exception { + String value = "button"; + JSONObject jsonObject = new JSONObject(); + jsonObject.put("key", "button"); + Whitebox.setInternalState(factory, "context", activity); + radioButton = Mockito.mock(RadioButton.class); + Whitebox.invokeMethod(factory, "checkSelectedRadioButton", listener, radioButton, value, jsonObject); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + Thread.sleep(TIMEOUT); + Mockito.verify(radioButton).setChecked(true); + } + + @Test + public void testSelectedTranslatedButton() throws Exception { + String value = "{\"value\":\"button\",\"text\":\"text\"}"; + JSONObject jsonObject = new JSONObject(); + jsonObject.put("key", "button"); + Whitebox.setInternalState(factory, "context", activity); + radioButton = Mockito.mock(RadioButton.class); + Whitebox.invokeMethod(factory, "checkSelectedRadioButton", listener, radioButton, value, jsonObject); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + Thread.sleep(TIMEOUT); + Mockito.verify(radioButton).setChecked(true); + } + + @Test + public void testShowDateDialog() throws Exception { + View view = Mockito.mock(View.class); + View radioButtonView = Mockito.mock(RadioButton.class); + radioButton = Mockito.mock(RadioButton.class); + String json = " {\n" + + " \"key\": \"Date_Birth\",\n" + + " \"openmrs_entity_parent\": \"\",\n" + + " \"openmrs_entity\": \"person\",\n" + + " \"openmrs_entity_id\": \"birthdate\",\n" + + " \"type\": \"date_picker\",\n" + + " \"hint\": \"Child's DOB\",\n" + + " \"label_info_title\": \"Child's Date of Birth\",\n" + + " \"label_info_text\": \"here is some text on this dialog\",\n" + + " \"expanded\": false,\n" + + " \"duration\": {\n" + + " \"label\": \"Age\"\n" + + " },\n" + + " \"min_date\": \"today-5y\",\n" + + " \"max_date\": \"today\",\n" + + " \"v_required\": {\n" + + " \"value\": \"true\",\n" + + " \"err\": \"Please enter the date of birth\"\n" + + " }\n" + + " }"; + Mockito.doReturn(radioButton).when(view).getTag(R.id.native_radio_button); + Mockito.doReturn("text:12-01-2000").when(radioButton).getText(); + Mockito.doReturn(jsonFormActivity).when(view).getTag((R.id.specify_context)); + Whitebox.setInternalState(factory, "context", jsonFormActivity); + Mockito.doReturn(new JSONObject(json)).when(radioButton).getTag(R.id.option_json_object); + Mockito.doReturn(radioButtonView).when(radioButtonView).getTag(R.id.specify_textview); + FragmentManager fragment = Mockito.spy(FragmentManager.class); + Whitebox.setInternalState(NativeRadioButtonFactory.class, "TAG", fragment); + NativeRadioButtonFactory.showDateDialog(view); + Assert.assertEquals("text:12-01-2000",radioButton.getText()); + } } diff --git a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactoryTest.java b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactoryTest.java index 36018e05c..ae060373f 100644 --- a/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactoryTest.java +++ b/android-json-form-wizard/src/test/java/com/vijay/jsonwizard/widgets/RepeatingGroupFactoryTest.java @@ -203,7 +203,7 @@ public void testUniqueChildElementKeyGenerationShouldContainChildKeyAsComponent( childElement.put(JsonFormConstants.KEY, childElementKey); AttachRepeatingGroupTask attachRepeatingGroupTask = new AttachRepeatingGroupTask(mock(LinearLayout.class), - 0, new HashMap(), widgetArgs, mock(ImageButton.class)); + 0, new HashMap<>(), widgetArgs, mock(ImageButton.class)); ReflectionHelpers.callInstanceMethod(attachRepeatingGroupTask, "addUniqueIdentifiers", diff --git a/android-json-form-wizard/src/test/resources/form_strings.properties b/android-json-form-wizard/src/test/resources/form_strings.properties new file mode 100644 index 000000000..e13a7e7f9 --- /dev/null +++ b/android-json-form-wizard/src/test/resources/form_strings.properties @@ -0,0 +1 @@ +form_strings.step1.danger_signs.danger_bleeding.text=Danger Bleeding \ No newline at end of file diff --git a/android-json-form-wizard/src/test/resources/form_strings_fr.properties b/android-json-form-wizard/src/test/resources/form_strings_fr.properties new file mode 100644 index 000000000..e69de29bb diff --git a/android-json-form-wizard/src/test/resources/form_strings_in.properties b/android-json-form-wizard/src/test/resources/form_strings_in.properties index b12a28c3f..3eef20eee 100644 --- a/android-json-form-wizard/src/test/resources/form_strings_in.properties +++ b/android-json-form-wizard/src/test/resources/form_strings_in.properties @@ -13,4 +13,5 @@ step1.been_treated.label = Pernah dirawat karena Malaria dalam 3 bulan terakhir? step1.been_treated.options.Yes.text = Ya step1.been_treated.options.No.text = Tidak step1.been_treated.options.not_answered.text = Tidak dijawab -step1.been_treated.v_required.err = Pernahkah pasien dirawat karena malaria dalam 3 bulan terakhir? \ No newline at end of file +step1.been_treated.v_required.err = Pernahkah pasien dirawat karena malaria dalam 3 bulan terakhir? +form_strings.step1.danger_signs.danger_bleeding.text=Bahaya Pendarahan \ No newline at end of file diff --git a/build.gradle b/build.gradle index decf54905..281084ca0 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,7 @@ buildscript { classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.30.0" classpath 'com.android.tools.build:gradle:4.2.2' classpath 'gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.12.0' + classpath 'com.android.tools.lint:lint:25.3.0' } } configure(allprojects) { project -> @@ -31,7 +32,7 @@ subprojects { group = 'org.smartregister' ext.androidToolsBuildGradle = '4.2.2' - ext.androidBuildToolsVersion = '30.0.2' + ext.androidBuildToolsVersion = '30.0.3' ext.androidMinSdkVersion = 18 ext.androidCompileSdkVersion = 31 ext.androidTargetSdkVersion = 31 @@ -52,9 +53,9 @@ subprojects { // Improve build server performance by allowing disabling of pre-dexing // (see http://tools.android.com/tech-docs/new-build-system/tips#TOC-Improving-Build-Server-performance.) project.plugins.whenPluginAdded { plugin -> - if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) { + if ("com.android.build.gradle.AppPlugin" == plugin.class.name) { project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs - } else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) { + } else if ("com.android.build.gradle.LibraryPlugin" == plugin.class.name) { project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs } } diff --git a/form_tester/src/main/assets/app.properties b/form_tester/src/main/assets/app.properties index 4129df05e..a2e8a9e3a 100644 --- a/form_tester/src/main/assets/app.properties +++ b/form_tester/src/main/assets/app.properties @@ -1 +1,2 @@ -widget.datepicker.is.numeric=true \ No newline at end of file +widget.datepicker.is.numeric=true +widget.value.translated=true \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1997d71f9..be834e97e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=3.0.1-SNAPSHOT +VERSION_NAME=3.1.2-SNAPSHOT VERSION_CODE=1 GROUP=org.smartregister POM_SETTING_DESCRIPTION=OpenSRP Client Native Form Json Wizard @@ -11,6 +11,7 @@ POM_SETTING_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt POM_SETTING_LICENCE_DIST=repo POM_SETTING_DEVELOPER_ID=opensrp POM_SETTING_DEVELOPER_NAME=OpenSRP Onadev +org.gradle.jvmargs=-Xmx4096M android.useAndroidX=true android.enableJetifier=true android.jetifier.ignorelist=shadows,bcprov-jdk15on diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 65666eb7c..69099560d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Fri Jun 17 11:20:13 EAT 2022 +#Mon Aug 01 17:52:45 EAT 2022 distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists diff --git a/maven.gradle b/maven.gradle index 098e612c6..a5e177e2d 100644 --- a/maven.gradle +++ b/maven.gradle @@ -132,4 +132,4 @@ afterEvaluate { project -> username getRepositoryUsername() password getRepositoryPassword() } -} +} \ No newline at end of file diff --git a/sample/src/main/assets/app.properties b/sample/src/main/assets/app.properties index 4129df05e..a2e8a9e3a 100644 --- a/sample/src/main/assets/app.properties +++ b/sample/src/main/assets/app.properties @@ -1 +1,2 @@ -widget.datepicker.is.numeric=true \ No newline at end of file +widget.datepicker.is.numeric=true +widget.value.translated=true \ No newline at end of file diff --git a/sample/src/main/assets/json.form/basic_form.json b/sample/src/main/assets/json.form/basic_form.json index 4fcc1c20b..edafe983e 100644 --- a/sample/src/main/assets/json.form/basic_form.json +++ b/sample/src/main/assets/json.form/basic_form.json @@ -190,37 +190,12 @@ "openmrs_entity_id": "", "type": "edit_text", "hint": "User age", - "edit_type": "name", + "edit_type": "number", "v_required": { "value": "true", - "err": "Please enter the last name" - }, - "v_regex": { - "value": "[A-Za-z\\s\\.\\-]*", - "err": "Please enter a valid name" + "err": "Please enter the age" } }, - { - "key": "user_gps", - "openmrs_entity_parent": "", - "openmrs_entity": "", - "openmrs_entity_id": "", - "openmrs_data_type": "text", - "type": "gps" - }, - { - "key": "user_calculation_one", - "openmrs_entity_parent": "", - "openmrs_entity": "concept", - "openmrs_entity_id": "165260AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "type": "hidden" - } - ] - }, - "step2": { - "title": "Basic Form Two", - "next": "step3", - "fields": [ { "key": "user_select", "openmrs_entity_parent": "", @@ -249,6 +224,27 @@ } ] }, + { + "key": "user_gps", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "openmrs_data_type": "text", + "type": "gps" + }, + { + "key": "user_calculation_one", + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_entity_id": "165260AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "type": "hidden" + } + ] + }, + "step2": { + "title": "Basic Form Two", + "next": "step3", + "fields": [ { "key": "user_normal_edit_text", "openmrs_entity_parent": "", diff --git a/sample/src/main/assets/json.form/rules_engine_demo.json b/sample/src/main/assets/json.form/rules_engine_demo.json index 410ddebb2..fb5d57fe7 100644 --- a/sample/src/main/assets/json.form/rules_engine_demo.json +++ b/sample/src/main/assets/json.form/rules_engine_demo.json @@ -287,7 +287,6 @@ "extra_info": "NOTE: kids are {kid_count} in number" } ], - "value": "none", "v_required": { "value": "true", "err": "Please select preferred gestational age" diff --git a/sample/src/main/assets/json.form/update_radio_button.json b/sample/src/main/assets/json.form/update_radio_button.json new file mode 100644 index 000000000..0f82d2ceb --- /dev/null +++ b/sample/src/main/assets/json.form/update_radio_button.json @@ -0,0 +1,107 @@ +{ + "count": "1", + "encounter_type": "Test", + "entity_id": "", + "relational_id": "", + "validate_on_submit": true, + "show_errors_on_submit": true, + "metadata": { + "start": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "start", + "openmrs_entity_id": "163137AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "2022-01-13 12:14:01" + }, + "end": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "end", + "openmrs_entity_id": "163138AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "2022-01-13 12:14:13" + }, + "today": { + "openmrs_entity_parent": "", + "openmrs_entity": "encounter", + "openmrs_entity_id": "encounter_date", + "value": "13-01-2022" + }, + "deviceid": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "deviceid", + "openmrs_entity_id": "163149AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "" + }, + "subscriberid": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "subscriberid", + "openmrs_entity_id": "163150AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "" + }, + "simserial": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "simserial", + "openmrs_entity_id": "163151AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "" + }, + "phonenumber": { + "openmrs_entity_parent": "", + "openmrs_entity": "concept", + "openmrs_data_type": "phonenumber", + "openmrs_entity_id": "163152AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "value": "" + }, + "encounter_location": "Kenya", + "look_up": { + "entity_id": "", + "value": "" + } + }, + "step1": { + "title": "Basic Form One", + "fields": [ + { + "key": "user_select", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "type": "native_radio", + "label": "Do you want to select anything", + "label_text_style": "bold", + "text_color": "#000000", + "label_info_text": "You can select every thing you want.", + "label_info_title": "User selection", + "options": [ + { + "key": "yes", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "text": "{{option.yes}}", + "translation_text": "option.yes" + }, + { + "key": "no", + "openmrs_entity_parent": "", + "openmrs_entity": "", + "openmrs_entity_id": "", + "text": "{{option.no}}", + "translation_text": "option.no" + } + ], + "value": { + "value": "yes", + "text": "option.yes" + } + } + ] + }, + "invisible_required_fields": "[]", + "details": { + "appVersionName": "0.0.6-SNAPSHOT", + "formVersion": "" + } +} \ No newline at end of file diff --git a/sample/src/main/assets/rule/sample-relevance-rules.yml b/sample/src/main/assets/rule/sample-relevance-rules.yml index 77d10be32..ffb992a9d 100644 --- a/sample/src/main/assets/rule/sample-relevance-rules.yml +++ b/sample/src/main/assets/rule/sample-relevance-rules.yml @@ -30,7 +30,7 @@ actions: name: step1_tobacco_cessation_toaster description: cease tobacco toaster priority: 1 -condition: "step1_hepb_immun_status > 10 && step1_hepb_immun_status < 30" +condition: "((step1_hepb_immun_status > 10 && step1_hepb_immun_status < 30) && step1_next_of_kin == 'hero')" actions: - "isRelevant = true" diff --git a/sample/src/main/java/org/smartregister/nativeform/MainActivity.java b/sample/src/main/java/org/smartregister/nativeform/MainActivity.java index d5f3dce8c..7a1f3469f 100644 --- a/sample/src/main/java/org/smartregister/nativeform/MainActivity.java +++ b/sample/src/main/java/org/smartregister/nativeform/MainActivity.java @@ -33,6 +33,7 @@ protected void onCreate(Bundle savedInstanceState) { findViewById(R.id.child_enrollment).setOnClickListener(this); findViewById(R.id.wizard_form).setOnClickListener(this); findViewById(R.id.native_form_basic).setOnClickListener(this); + findViewById(R.id.update_radio_button).setOnClickListener(this); findViewById(R.id.rules_engine_skip_logic).setOnClickListener(this); findViewById(R.id.numbers_selector_widget).setOnClickListener(this); findViewById(R.id.generic_dialog_button).setOnClickListener(this); @@ -167,6 +168,26 @@ public void startForm(int jsonFormActivityRequestCode, String formName, String e startActivityForResult(intent, jsonFormActivityRequestCode); break; } + case "update_radio_button": { + Intent intent = new Intent(this, JsonWizardFormActivity.class); + intent.putExtra("json", jsonForm.toString()); + Log.d(getClass().getName(), "form is " + jsonForm.toString()); + + Form form = new Form(); + form.setName(getString(R.string.update_radio_button)); + form.setWizard(true); + form.setActionBarBackground(R.color.profile_actionbar); + form.setNavigationBackground(R.color.profile_navigation); + form.setHideSaveLabel(true); + form.setNextLabel(getString(R.string.next)); + form.setPreviousLabel(getString(R.string.previous)); + form.setSaveLabel(getString(R.string.save)); + form.setBackIcon(R.drawable.ic_icon_positive); + intent.putExtra(JsonFormConstants.JSON_FORM_KEY.FORM, form); + + startActivityForResult(intent, jsonFormActivityRequestCode); + break; + } case "validation_form": { Intent intent = new Intent(this, JsonWizardFormActivity.class); intent.putExtra("json", jsonForm.toString()); @@ -223,7 +244,6 @@ public void startForm(int jsonFormActivityRequestCode, String formName, String e .equalsIgnoreCase(ZEIR_ID)) { jsonObject.remove(VALUE); jsonObject.put(VALUE, entityId); - continue; } } @@ -254,6 +274,9 @@ public void onClick(View view) { case R.id.native_form_basic: startForm(REQUEST_CODE_GET_JSON, "basic_form", null, false); break; + case R.id.update_radio_button: + startForm(REQUEST_CODE_GET_JSON, "update_radio_button", null, false); + break; case R.id.rules_engine_skip_logic: startForm(REQUEST_CODE_GET_JSON, "rules_engine_demo", null, false); break; diff --git a/sample/src/main/res/layout/content_main.xml b/sample/src/main/res/layout/content_main.xml index 00f182300..b7fa8e7e1 100644 --- a/sample/src/main/res/layout/content_main.xml +++ b/sample/src/main/res/layout/content_main.xml @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="BIRTH REGISTER" + android:text="@string/birth_register" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -31,7 +31,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="WIZARD (MULTI-STEP FORM)" + android:text="@string/wizard_multi_step_form" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -40,7 +40,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="RULES ENGINE LOGIC" + android:text="@string/rules_engine_logic" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -50,7 +50,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="CONSTRAINTS" + android:text="@string/constraints" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -59,7 +59,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="GENERIC POPUP" + android:text="@string/generic_popup" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -69,7 +69,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="FORM VALIDATION" + android:text="@string/form_validation" android:textColor="@android:color/white" android:theme="@style/NativeFormsAppTheme" /> @@ -78,7 +78,15 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="Basic Form" + android:text="@string/basic_form" + android:textColor="@android:color/white" + android:theme="@style/NativeFormsAppTheme" /> +