Skip to content

Commit

Permalink
Merge branch 'master' into tt-09-2020
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-karuri authored Sep 15, 2020
2 parents bbde3ea + 8e64e8b commit c7b0adc
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.vijay.jsonwizard.presenters.JsonFormFragmentPresenter;
import com.vijay.jsonwizard.task.AttachRepeatingGroupTask;
import com.vijay.jsonwizard.utils.FormUtils;
import com.vijay.jsonwizard.utils.ValidationStatus;
import com.vijay.jsonwizard.validators.edittext.MaxNumericValidator;
import com.vijay.jsonwizard.validators.edittext.MinNumericValidator;
import com.vijay.jsonwizard.validators.edittext.RequiredValidator;
Expand All @@ -51,6 +52,11 @@

import static com.vijay.jsonwizard.constants.JsonFormConstants.FIELDS;
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;

/**
Expand All @@ -59,31 +65,29 @@
public class RepeatingGroupFactory implements FormWidgetFactory {

private static Map<Integer, String> repeatingGroupLayouts = new HashMap<>();
private final String REFERENCE_EDIT_TEXT_HINT = "reference_edit_text_hint";
public static final String REFERENCE_EDIT_TEXT_HINT = "reference_edit_text_hint";
private final String REPEATING_GROUP_LABEL = "repeating_group_label";
private final String REFERENCE_EDIT_TEXT = "reference_edit_text";
private final String REPEATING_GROUP_MAX = "repeating_group_max";
private final String REPEATING_GROUP_MIN = "repeating_group_min";
protected int MAX_NUM_REPEATING_GROUPS = 35;
protected int MIN_NUM_REPEATING_GROUPS = 0;
private ImageButton doneButton;
private WidgetArgs widgetArgs;


@Override
public List<View> getViewsFromJson(final String stepName, final Context context, final JsonFormFragment formFragment, final JSONObject jsonObject, final CommonListener listener, final boolean popup) throws Exception {
List<View> views = new ArrayList<>(1);
LinearLayout rootLayout = getRootLayout(context);

final int rootLayoutId = View.generateViewId();
doneButton = rootLayout.findViewById(R.id.btn_repeating_group_done);

rootLayout.setId(rootLayoutId);
views.add(rootLayout);

JSONArray repeatingGroupLayout = jsonObject.getJSONArray(VALUE);
repeatingGroupLayouts.put(rootLayoutId, repeatingGroupLayout.toString());

this.widgetArgs = new WidgetArgs()
final WidgetArgs widgetArgs = new WidgetArgs()
.withStepName(stepName)
.withContext(context)
.withFormFragment(formFragment)
Expand All @@ -92,15 +96,19 @@ public List<View> getViewsFromJson(final String stepName, final Context context,
.withPopup(popup);

final MaterialEditText referenceEditText = rootLayout.findViewById(R.id.reference_edit_text);
final ImageButton doneButton = rootLayout.findViewById(R.id.btn_repeating_group_done);

final String referenceEditTextHint = jsonObject.optString(REFERENCE_EDIT_TEXT_HINT, context.getString(R.string.enter_number_of_repeating_group_items));
final String repeatingGroupLabel = jsonObject.optString(REPEATING_GROUP_LABEL, context.getString(R.string.repeating_group_item));
String remoteReferenceEditText = jsonObject.optString(REFERENCE_EDIT_TEXT);

setRepeatingGroupNumLimits();
setRepeatingGroupNumLimits(widgetArgs);

// Enables us to fetch this value from a previous edit_text & disable this one
retrieveRepeatingGroupCountFromRemoteReferenceEditText(rootLayout, (JsonApi) context, referenceEditText, remoteReferenceEditText);
setUpReferenceEditText(referenceEditText, referenceEditTextHint, repeatingGroupLabel);
retrieveRepeatingGroupCountFromRemoteReferenceEditText(rootLayout, getJsonApi(widgetArgs),
referenceEditText, remoteReferenceEditText, doneButton, widgetArgs);
setUpReferenceEditText(doneButton, referenceEditText, referenceEditTextHint,
repeatingGroupLabel, getRepeatingGroupCountObj(widgetArgs), widgetArgs);

// Disable the done button if the reference edit text being used is remote & has a valid value
if (isRemoteReferenceValueUsed(referenceEditText)) {
Expand All @@ -109,18 +117,46 @@ public List<View> getViewsFromJson(final String stepName, final Context context,
doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addOnDoneAction(referenceEditText);
addOnDoneAction(referenceEditText, doneButton, widgetArgs);
}
});
}

((JsonApi) context).addFormDataView(referenceEditText);
setViewTags(rootLayout);
prepareViewChecks(rootLayout, context);
setViewTags(rootLayout, widgetArgs);
prepareViewChecks(rootLayout, context, widgetArgs);

return views;
}

/**
* Returns the object that holds the repeating group count
*
* @return
* @throws JSONException
*/
private JSONObject getRepeatingGroupCountObj(WidgetArgs widgetArgs) throws JSONException {

String repeatingGroupCountObjKey = widgetArgs.getJsonObject().get(KEY) + "_count";
JSONArray stepFields = getStepFields(getJsonApi(widgetArgs).getStep(widgetArgs.getStepName()));
JSONObject repeatingGroupCountObj = FormUtils.getFieldJSONObject(stepFields, repeatingGroupCountObjKey);
// prevents re-adding the count object during form traversals
if (repeatingGroupCountObj != null) {
return repeatingGroupCountObj;
}

repeatingGroupCountObj = new JSONObject();
repeatingGroupCountObj.put(KEY, repeatingGroupCountObjKey);
repeatingGroupCountObj.put(OPENMRS_ENTITY_PARENT, "");
repeatingGroupCountObj.put(OPENMRS_ENTITY, "");
repeatingGroupCountObj.put(OPENMRS_ENTITY_ID, "");
repeatingGroupCountObj.put(TYPE, "");
repeatingGroupCountObj.put(TEXT, widgetArgs.getJsonObject().get(REFERENCE_EDIT_TEXT_HINT));
stepFields.put(repeatingGroupCountObj);

return repeatingGroupCountObj;
}

@Override
public List<View> getViewsFromJson(final String stepName, Context context, JsonFormFragment formFragment, JSONObject jsonObject, CommonListener listener) throws Exception {
return getViewsFromJson(stepName, context, formFragment, jsonObject, listener, false);
Expand All @@ -139,7 +175,7 @@ protected LinearLayout getRootLayout(Context context) {
/**
* Sets min and max number of repeating groups
*/
private void setRepeatingGroupNumLimits() {
private void setRepeatingGroupNumLimits(WidgetArgs widgetArgs) {
try {
MIN_NUM_REPEATING_GROUPS = widgetArgs.getJsonObject().optInt(REPEATING_GROUP_MIN, MIN_NUM_REPEATING_GROUPS);
MAX_NUM_REPEATING_GROUPS = widgetArgs.getJsonObject().optInt(REPEATING_GROUP_MAX, MAX_NUM_REPEATING_GROUPS);
Expand All @@ -148,7 +184,7 @@ private void setRepeatingGroupNumLimits() {
}
}

private void setViewTags(@NonNull LinearLayout rootLayout) {
private void setViewTags(@NonNull LinearLayout rootLayout, WidgetArgs widgetArgs) {
JSONArray canvasIds = new JSONArray();
canvasIds.put(rootLayout.getId());
rootLayout.setTag(R.id.canvas_ids, canvasIds.toString());
Expand All @@ -158,7 +194,7 @@ private void setViewTags(@NonNull LinearLayout rootLayout) {
rootLayout.setTag(R.id.address, widgetArgs.getStepName() + ":" + widgetArgs.getJsonObject().optString(KEY));
}

private void prepareViewChecks(@NonNull LinearLayout view, @NonNull Context context) {
private void prepareViewChecks(@NonNull LinearLayout view, @NonNull Context context, WidgetArgs widgetArgs) {
String relevance = widgetArgs.getJsonObject().optString(JsonFormConstants.RELEVANCE);
String constraints = widgetArgs.getJsonObject().optString(JsonFormConstants.CONSTRAINTS);
String calculation = widgetArgs.getJsonObject().optString(JsonFormConstants.CALCULATION);
Expand All @@ -179,7 +215,13 @@ private void prepareViewChecks(@NonNull LinearLayout view, @NonNull Context cont
}
}

private void retrieveRepeatingGroupCountFromRemoteReferenceEditText(final @NonNull View rootLayout, @NonNull JsonApi context, @NonNull final MaterialEditText referenceEditText, @Nullable String remoteReferenceEditTextAddress) throws JSONException {
private void retrieveRepeatingGroupCountFromRemoteReferenceEditText(final @NonNull View rootLayout,
@NonNull JsonApi context,
@NonNull final MaterialEditText referenceEditText,
@Nullable String remoteReferenceEditTextAddress,
@NonNull final ImageButton doneButton,
@NonNull final WidgetArgs widgetArgs) throws JSONException {

if (!TextUtils.isEmpty(remoteReferenceEditTextAddress) && remoteReferenceEditTextAddress.contains(":")) {
String finalRemoteReferenceEditTextAddress = remoteReferenceEditTextAddress.trim();
String[] addressSections = finalRemoteReferenceEditTextAddress.split(":");
Expand All @@ -190,7 +232,7 @@ private void retrieveRepeatingGroupCountFromRemoteReferenceEditText(final @NonNu
JSONObject stepJsonObject = context.getmJSONObject().optJSONObject(remoteReferenceEditTextStep);

if (stepJsonObject != null) {
JSONArray fields = stepJsonObject.optJSONArray(FIELDS);
JSONArray fields = getStepFields(stepJsonObject);

for (int i = 0; i < fields.length(); i++) {
JSONObject stepField = fields.optJSONObject(i);
Expand All @@ -205,9 +247,11 @@ private void retrieveRepeatingGroupCountFromRemoteReferenceEditText(final @NonNu
// Start the repeating groups
Object visibilityTag = rootLayout.getTag(R.id.relevance_decided);
if (visibilityTag != null && (boolean) visibilityTag) {
attachRepeatingGroup(referenceEditText.getParent().getParent(), remoteReferenceValue);
attachRepeatingGroup(referenceEditText.getParent().getParent(),
remoteReferenceValue, doneButton, widgetArgs);
} else {
setGlobalLayoutListener(rootLayout, referenceEditText, remoteReferenceValue);
setGlobalLayoutListener(rootLayout, referenceEditText,
remoteReferenceValue, doneButton, widgetArgs);
}
} catch (NumberFormatException ex) {
Timber.e(ex);
Expand All @@ -221,22 +265,33 @@ private void retrieveRepeatingGroupCountFromRemoteReferenceEditText(final @NonNu
}

@VisibleForTesting
protected void setGlobalLayoutListener(@NonNull final View rootLayout, @NonNull final MaterialEditText referenceEditText, final int remoteReferenceValue) {
protected void setGlobalLayoutListener(@NonNull final View rootLayout,
@NonNull final MaterialEditText referenceEditText,
@NonNull final int remoteReferenceValue,
@NonNull final ImageButton doneButton,
@NonNull final WidgetArgs widgetArgs) {

rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override
public void onGlobalLayout() {
Object visibilityTag = rootLayout.getTag(R.id.relevance_decided);
if (visibilityTag != null && (boolean) visibilityTag) {
attachRepeatingGroup(referenceEditText.getParent().getParent(), remoteReferenceValue);
attachRepeatingGroup(referenceEditText.getParent().getParent(),
remoteReferenceValue, doneButton, widgetArgs);

rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}

private void setUpReferenceEditText(final MaterialEditText referenceEditText, String referenceEditTextHint, String repeatingGroupLabel) throws JSONException {
private void setUpReferenceEditText(final ImageButton doneButton,
final MaterialEditText referenceEditText,
final String referenceEditTextHint,
final String repeatingGroupLabel,
final JSONObject repeatingGroupCount,
final WidgetArgs widgetArgs) throws JSONException {
// We should disable this edit_text if another referenced edit text is being used
Context context = widgetArgs.getContext();
if (isRemoteReferenceValueUsed(referenceEditText)) {
Expand All @@ -246,7 +301,7 @@ private void setUpReferenceEditText(final MaterialEditText referenceEditText, St
@Override
public boolean onEditorAction(TextView focusTextView, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
addOnDoneAction(focusTextView);
addOnDoneAction(focusTextView, doneButton, widgetArgs);
return true;
}
return false;
Expand All @@ -255,7 +310,7 @@ public boolean onEditorAction(TextView focusTextView, int actionId, KeyEvent eve
}

referenceEditText.setTag(R.id.address, widgetArgs.getStepName() + ":" + widgetArgs.getJsonObject().getString(KEY));
attachTextChangedListener(referenceEditText);
attachTextChangedListener(referenceEditText, doneButton, repeatingGroupCount, widgetArgs);
referenceEditText.setHint(referenceEditTextHint);
referenceEditText.setTag(R.id.repeating_group_label, repeatingGroupLabel);
referenceEditText.setTag(R.id.extraPopup, false);
Expand All @@ -274,7 +329,11 @@ public boolean onEditorAction(TextView focusTextView, int actionId, KeyEvent eve
}
}

private void attachTextChangedListener(final MaterialEditText referenceEditText) {
private void attachTextChangedListener(final MaterialEditText referenceEditText,
final ImageButton doneButton,
final JSONObject repeatingGroupCount,
final WidgetArgs widgetArgs) {

referenceEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Expand All @@ -289,11 +348,23 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
@Override
public void afterTextChanged(Editable s) {
doneButton.setImageResource(R.drawable.ic_done_grey);
JsonFormFragmentPresenter.validate(widgetArgs.getFormFragment(), referenceEditText, false);
ValidationStatus validationStatus = JsonFormFragmentPresenter
.validate(widgetArgs.getFormFragment(), referenceEditText, false);
if (validationStatus.isValid()) {
writeJsonObjectValue(repeatingGroupCount, s.toString());
}
}
});
}

private void writeJsonObjectValue(JSONObject jsonObject, String value) {
try {
jsonObject.put(VALUE, value);
} catch (JSONException e) {
Timber.e(e);
}
}

private void addRequiredValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_REQUIRED);
if (requiredObject != null) {
Expand All @@ -305,23 +376,26 @@ private void addRequiredValidator(JSONObject jsonObject, MaterialEditText editTe
}
}

protected void addOnDoneAction(TextView textView) {
protected void addOnDoneAction(final TextView textView, final ImageButton doneButton, final WidgetArgs widgetArgs) {
try {
InputMethodManager inputMethodManager = (InputMethodManager) widgetArgs.getFormFragment().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(textView.getWindowToken(), 0);
textView.clearFocus();
attachRepeatingGroup(textView.getParent().getParent(), Integer.parseInt(textView.getText().toString()));
attachRepeatingGroup(textView.getParent().getParent(),
Integer.parseInt(textView.getText().toString()), doneButton, widgetArgs);
} catch (Exception e) {
Timber.e(e);
}
}

private void attachRepeatingGroup(final ViewParent parent, final int numRepeatingGroups) {
private void attachRepeatingGroup(final ViewParent parent, final int numRepeatingGroups,
final ImageButton doneButton, final WidgetArgs widgetArgs) {
if (numRepeatingGroups > MAX_NUM_REPEATING_GROUPS) {
return;
}

new AttachRepeatingGroupTask(parent, numRepeatingGroups, repeatingGroupLayouts, widgetArgs, doneButton).execute();
new AttachRepeatingGroupTask(parent, numRepeatingGroups, repeatingGroupLayouts,
widgetArgs, doneButton).execute();
}

protected int getLayout() {
Expand All @@ -337,4 +411,13 @@ public int remoteReferenceValue(@NonNull View referenceEditText) {
Object tagValue = referenceEditText.getTag(R.id.repeating_group_remote_reference_value);
return tagValue instanceof Integer ? (int) tagValue : 0;
}

private JsonApi getJsonApi(WidgetArgs widgetArgs) {
Context context = widgetArgs.getContext();
return context instanceof JsonApi ? (JsonApi) context : null;
}

private JSONArray getStepFields (JSONObject step) {
return step.optJSONArray(FIELDS);
}
}
Loading

0 comments on commit c7b0adc

Please sign in to comment.