Skip to content

Commit

Permalink
[ANDROAPP-1540] Multi selection for option set in programs (#3500)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo <[email protected]>
  • Loading branch information
Balcan authored Feb 28, 2024
1 parent 5839900 commit 68db6e6
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.dhis2.usescases.general.ActivityGlobalAbstract;
import org.hisp.dhis.android.core.D2;
import org.hisp.dhis.android.core.D2Manager;
import org.hisp.dhis.android.core.common.ValueType;

import java.io.BufferedReader;
import java.io.IOException;
Expand All @@ -39,6 +40,24 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
loadCrashControl();
loadFeatureConfig();
loadConflicts();
loadMultiText();
}

private void loadMultiText() {
D2 d2 = D2Manager.getD2();
boolean hasMultiText = !d2.dataElementModule().dataElements().byValueType().eq(ValueType.MULTI_TEXT).blockingIsEmpty();
binding.multitext.setText(hasMultiText ? "REVERT" : "FORCE MULTITEXT");
binding.multitext.setOnClickListener(view -> {
if (hasMultiText) {
d2.databaseAdapter().execSQL(
"UPDATE DataElement SET valueType = \"TEXT\" WHERE valueType = \"MULTI_TEXT\" AND optionSet IS NOT null"
);
} else {
d2.databaseAdapter().execSQL(
"UPDATE DataElement SET valueType = \"MULTI_TEXT\" WHERE valueType = \"TEXT\" AND optionSet IS NOT null"
);
}
});
}

private void loadConflicts() {
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/res/layout/development_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,32 @@
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="UI Components" />


<TextView
style="@style/TextPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@color/primaryAlpha"
android:text="Force Multi text"
android:textColor="@color/colorAccent" />

<TextView
style="@style/TextSecondary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Transforms TEXT data elements with option sets into MULTI TEXT."
android:textColor="@color/text_color" />

<com.google.android.material.button.MaterialButton
android:id="@+id/multitext"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="UPDATE" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fun TrackedEntityAttributeValue.userFriendlyValue(d2: D2): String? {
}

if (check(d2, attribute.valueType(), attribute.optionSet()?.uid(), value()!!)) {
attribute.optionSet()?.let {
attribute.optionSet()?.takeIf { attribute.valueType() != ValueType.MULTI_TEXT }?.let {
return checkOptionSetValue(d2, it.uid(), value()!!)
} ?: return checkValueTypeValue(d2, attribute.valueType(), value()!!)
} else {
Expand All @@ -45,7 +45,7 @@ fun TrackedEntityDataValue?.userFriendlyValue(d2: D2): String? {
if (dataElement == null) {
return null
} else if (check(d2, dataElement.valueType(), dataElement.optionSet()?.uid(), value()!!)) {
dataElement.optionSet()?.let {
dataElement.optionSet()?.takeIf { dataElement.valueType() != ValueType.MULTI_TEXT }?.let {
return checkOptionSetValue(d2, it.uid(), value()!!)
} ?: return checkValueTypeValue(d2, dataElement.valueType(), value()!!)
} else {
Expand Down Expand Up @@ -191,14 +191,13 @@ fun TrackedEntityDataValueObjectRepository.blockingGetValueCheck(

private fun check(d2: D2, valueType: ValueType?, optionSetUid: String?, value: String): Boolean {
return when {
optionSetUid != null -> {
valueType != ValueType.MULTI_TEXT && optionSetUid != null -> {
val optionByCodeExist = d2.optionModule().options().byOptionSetUid().eq(optionSetUid)
.byCode().eq(value).one().blockingExists()
val optionByNameExist = d2.optionModule().options().byOptionSetUid().eq(optionSetUid)
.byDisplayName().eq(value).one().blockingExists()
optionByCodeExist || optionByNameExist
}

valueType != null -> {
if (valueType.isNumeric) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ class FieldViewModelFactoryImpl(
style = uiStyleProvider.provideStyle(valueType),
hint = hintProvider.provideDateHint(valueType),
description = description,
valueType = valueType,
valueType = if (optionSet != null && valueType == ValueType.TEXT) ValueType.MULTI_TEXT else valueType,
legend = legendValueProvider.provideLegendValue(id, value),
optionSet = optionSet,
optionSet = if (valueType == ValueType.MULTI_TEXT) null else optionSet,
allowFutureDates = allowFutureDates,
uiEventFactory = UiEventFactoryImpl(
id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,18 @@ fun FieldProvider(
)
}

ValueType.MULTI_TEXT -> {
ProvideMultiSelectionInput(
modifier = modifierWithFocus,
fieldUiModel = fieldUiModel,
intentHandler = intentHandler,
)
}

ValueType.REFERENCE,
ValueType.GEOJSON,
ValueType.USERNAME,
ValueType.TRACKER_ASSOCIATE,
ValueType.MULTI_TEXT,
null,
-> {
InputNotSupported(title = fieldUiModel.label)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.dhis2.form.ui.provider.inputfield

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import org.dhis2.form.extensions.inputState
import org.dhis2.form.extensions.legend
import org.dhis2.form.extensions.supportingText
import org.dhis2.form.model.FieldUiModel
import org.dhis2.form.ui.intent.FormIntent
import org.hisp.dhis.mobile.ui.designsystem.component.CheckBoxData
import org.hisp.dhis.mobile.ui.designsystem.component.InputMultiSelection

@Composable
internal fun ProvideMultiSelectionInput(
modifier: Modifier,
fieldUiModel: FieldUiModel,
intentHandler: (FormIntent) -> Unit,
) {
val optionsToDisplay = fieldUiModel.optionSetConfiguration?.optionsToDisplay() ?: emptyList()
val data = optionsToDisplay.map { option ->
CheckBoxData(
uid = option.uid(),
checked = option.code()?.let { fieldUiModel.value?.contains(it) } ?: false,
enabled = true,
textInput = option.displayName() ?: "",
)
}

InputMultiSelection(
modifier = modifier,
title = fieldUiModel.label,
items = data,
state = fieldUiModel.inputState(),
supportingTextData = fieldUiModel.supportingText(),
legendData = fieldUiModel.legend(),
isRequired = fieldUiModel.mandatory,
onItemsSelected = {
val checkedValues = it.filter { item -> item.checked }.mapNotNull {
optionsToDisplay.find { option -> option.uid() == it.uid }?.code()
}

intentHandler(
FormIntent.OnSave(
fieldUiModel.uid,
checkedValues.joinToString(separator = ","),
fieldUiModel.valueType,
),
)
},
onClearItemSelection = {
intentHandler(FormIntent.ClearValue(fieldUiModel.uid))
},
)
}

0 comments on commit 68db6e6

Please sign in to comment.