Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ANDROAPP-1540] Multi selection for option set in programs #3500

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
},
)
}
Loading