Skip to content

Commit

Permalink
fix: [ANDROAPP-6021] displays first 50 options (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
ferdyrod authored Apr 29, 2024
1 parent 41f5c76 commit e9b76f0
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,25 @@ fun InputDropDownScreen() {
selectedItem = selectedItem3,
)
Spacer(Modifier.size(Spacing.Spacing18))

SubTitle("Input Dropdown with 5000 items ", textColor = TextColor.OnSurfaceVariant)
val dropdownItems = mutableListOf<DropdownItem>()
for (i in 1..5000) {
dropdownItems.add(DropdownItem("$i"))
}

InputDropDown(
title = "Label",
state = InputShellState.UNFOCUSED,
dropdownItems = dropdownItems,
onResetButtonClicked = {
selectedItem = null
},
onItemSelected = {
selectedItem = it
},
selectedItem = selectedItem,
)
Spacer(Modifier.size(Spacing.Spacing18))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,35 @@ fun MultiSelectInputScreen() {
legendData = null,
supportingTextData = null,
)

val multiSelectItems = mutableListOf<CheckBoxData>()
for (i in 1..5000) {
multiSelectItems.add(
CheckBoxData(
uid = "uid-$i",
checked = i == 2,
enabled = true,
textInput = "Opt. $i",
),
)
}

InputMultiSelection(
items = multiSelectItems,
title = "Multi Select more than 5000 items",
state = InputShellState.UNFOCUSED,
onItemsSelected = { selectedItems ->
selectedItems.forEach { selectedItem ->
val index = multiSelectItems.indexOfFirst { it.uid == selectedItem.uid }
multiSelectItems[index] = selectedItem
}
},
onClearItemSelection = {
multiSelectItems.replaceAll { it.copy(checked = false) }
},
isRequired = false,
legendData = null,
supportingTextData = null,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import org.hisp.dhis.mobile.ui.designsystem.resource.provideStringResource
import org.hisp.dhis.mobile.ui.designsystem.theme.DHIS2SCustomTextStyles
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing.Spacing0
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing.Spacing16
Expand All @@ -45,6 +46,7 @@ import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor
import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor

private const val MAX_DROPDOWN_ITEMS = 6
private const val MAX_DROPDOWN_ITEMS_TO_SHOW = 50

/**
* DHIS2 Input dropdown. Wraps DHIS · [DropdownInputField].
Expand Down Expand Up @@ -81,7 +83,8 @@ fun InputDropDown(
onResetButtonClicked: () -> Unit,
onItemSelected: (DropdownItem) -> Unit,
showSearchBar: Boolean = true,
noResultsFoundString: String = "No results found",
noResultsFoundString: String = provideStringResource("no_results_found"),
searchToFindMoreString: String = provideStringResource("search_to_see_more"),
) {
val focusRequester = remember { FocusRequester() }
var showDropdown by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -113,8 +116,12 @@ fun InputDropDown(
if (showDropdown) {
var searchQuery by remember { mutableStateOf("") }

val filteredOptions =
dropdownItems.filter { it.label.contains(searchQuery, ignoreCase = true) }
var filteredOptions = dropdownItems

if (searchQuery.isNotEmpty()) {
filteredOptions =
dropdownItems.filter { it.label.contains(searchQuery, ignoreCase = true) }
}

BottomSheetShell(
modifier = Modifier.testTag("INPUT_DROPDOWN_BOTTOM_SHEET"),
Expand All @@ -126,16 +133,27 @@ fun InputDropDown(
.padding(top = Spacing8),
) {
if (filteredOptions.isNotEmpty()) {
filteredOptions.forEachIndexed { index, item ->
DropdownItem(
modifier = Modifier.testTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEM_$index"),
item = item,
selected = selectedItem == item,
contentPadding = PaddingValues(Spacing8),
onItemClick = {
onItemSelected(item)
showDropdown = false
},
filteredOptions
.take(MAX_DROPDOWN_ITEMS_TO_SHOW)
.forEachIndexed { index, item ->
DropdownItem(
modifier = Modifier.testTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEM_$index"),
item = item,
selected = selectedItem == item,
contentPadding = PaddingValues(Spacing8),
onItemClick = {
onItemSelected(item)
showDropdown = false
},
)
}
if (filteredOptions.size > MAX_DROPDOWN_ITEMS_TO_SHOW) {
Text(
text = searchToFindMoreString,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor

private const val INLINE_CHECKBOXES_MIN_REQ_ITEMS = 6
private const val MAX_CHECKBOXES_ITEMS_TO_SHOW = 50

/**
* DHIS2 input multi selection component.
Expand Down Expand Up @@ -69,6 +70,7 @@ fun InputMultiSelection(
onItemsSelected: (List<CheckBoxData>) -> Unit,
modifier: Modifier = Modifier,
noResultsFoundString: String = provideStringResource("no_results_found"),
searchToFindMoreString: String = provideStringResource("search_to_see_more"),
doneButtonText: String = provideStringResource("done"),
inputStyle: InputStyle = InputStyle.DataInputStyle(),
onClearItemSelection: () -> Unit,
Expand Down Expand Up @@ -224,6 +226,7 @@ fun InputMultiSelection(
items = items,
title = title,
noResultsFoundString = noResultsFoundString,
searchToFindMoreString = searchToFindMoreString,
doneButtonText = doneButtonText,
onItemsSelected = {
onItemsSelected(it)
Expand Down Expand Up @@ -268,6 +271,7 @@ fun MultiSelectBottomSheet(
items: List<CheckBoxData>,
title: String,
noResultsFoundString: String,
searchToFindMoreString: String,
doneButtonText: String,
onItemsSelected: (List<CheckBoxData>) -> Unit,
onDismiss: () -> Unit,
Expand All @@ -289,19 +293,30 @@ fun MultiSelectBottomSheet(
.padding(top = Spacing.Spacing8),
) {
if (filteredOptions.isNotEmpty()) {
filteredOptions.forEachIndexed { index, item ->
CheckBox(
checkBoxData = item.copy(
textInput = bottomSheetItemLabel(
text = item.textInput!!,
searchQuery = searchQuery,
filteredOptions
.take(MAX_CHECKBOXES_ITEMS_TO_SHOW)
.forEachIndexed { index, item ->
CheckBox(
checkBoxData = item.copy(
textInput = bottomSheetItemLabel(
text = item.textInput!!,
searchQuery = searchQuery,
),
),
),
onCheckedChange = {
filteredOptions[index] = item.copy(checked = it)
itemsModified[index] = item.copy(checked = it)
},
modifier = Modifier.fillMaxWidth(),
onCheckedChange = {
filteredOptions[index] = item.copy(checked = it)
itemsModified[index] = item.copy(checked = it)
},
modifier = Modifier.fillMaxWidth(),
)
}
if (filteredOptions.size > MAX_CHECKBOXES_ITEMS_TO_SHOW) {
Text(
text = searchToFindMoreString,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@
<string name="select_date">Select date</string>
<string name="date_out_of_range">Date out of range </string>
<string name="wrong_hour_format">Incorrect time format </string>
<string name="search_to_see_more">Not all options are displayed.\n Search to see more.</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -397,4 +397,48 @@ class InputDropDownTest {
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET").assertDoesNotExist()
assert(selectedItem == dropdownItems[2])
}

@Test
fun shouldShowSearchForMoreOptionTextWhenMoreThan50Option() {
val dropdownItems = mutableListOf<DropdownItem>()
for (i in 1..100) {
dropdownItems.add(
DropdownItem("Option $i"),
)
}

val searchSemantics = "Search"

rule.setContent {
InputDropDown(
title = "Label",
dropdownItems = dropdownItems,
supportingTextData = listOf(SupportingTextData("Supporting text", SupportingTextState.DEFAULT)),
state = InputShellState.UNFOCUSED,
onResetButtonClicked = {},
onItemSelected = {},
)
}
rule.onNodeWithTag("INPUT_DROPDOWN").assertExists()
rule.onNodeWithTag("INPUT_DROPDOWN_ARROW_BUTTON").performClick()
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET").assertExists()
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEMS").onChildren().assertCountEquals(51)
rule.onNodeWithContentDescription(searchSemantics).assertExists()

rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEMS").onChildren().assertCountEquals(51)
rule.onNodeWithText("Not all options are displayed.\\n Search to see more.").assertExists()

// Search
rule.onNodeWithContentDescription(searchSemantics).performTextInput("5")
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEMS").onChildren().assertCountEquals(19)
rule.onNodeWithText("Not all options are displayed.\\n Search to see more.").assertDoesNotExist()

rule.onNodeWithContentDescription(searchSemantics).performTextInput("55")
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEMS").onChildren().assertCountEquals(1)
rule.onNodeWithText("Not all options are displayed.\\n Search to see more.").assertDoesNotExist()

rule.onNodeWithContentDescription(searchSemantics).performTextInput("555")
rule.onNodeWithTag("INPUT_DROPDOWN_BOTTOM_SHEET_ITEMS").onChildren().assertCountEquals(1)
rule.onNodeWithText("No results found").assertExists()
}
}

0 comments on commit e9b76f0

Please sign in to comment.