Skip to content

Commit

Permalink
Adapt input org unit for implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
xavimolloy committed Oct 11, 2023
1 parent ed8f84b commit 9c13cf3
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
package org.hisp.dhis.mobile.ui.designsystem.component

import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowDropDown
import androidx.compose.material.icons.outlined.Cancel
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.input.ImeAction
import org.hisp.dhis.mobile.ui.designsystem.resource.provideDHIS2Icon
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing
import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor

/**
* DHIS2 Input org unit. Wraps DHIS · [BasicTextInput].
Expand All @@ -17,11 +33,9 @@ import org.hisp.dhis.mobile.ui.designsystem.resource.provideDHIS2Icon
* @param legendData manages the legendComponent
* @param inputText manages the value of the text in the input field
* @param isRequiredField controls whether the field is mandatory or not
* @param onNextClicked gives access to the imeAction event
* @param onValueChanged gives access to the onValueChanged event
* @param onFocusChanged gives access to the onFocusChanged returns true if
* item is focused
* @param imeAction controls the imeAction button to be shown
* @param modifier allows a modifier to be passed externally
* @param onOrgUnitActionCLicked callback to when org unit button is clicked
*/
Expand All @@ -33,27 +47,67 @@ fun InputOrgUnit(
legendData: LegendData? = null,
inputText: String? = null,
isRequiredField: Boolean = false,
onNextClicked: (() -> Unit)? = null,
onValueChanged: ((String?) -> Unit)? = null,
onFocusChanged: ((Boolean) -> Unit)? = null,
imeAction: ImeAction = ImeAction.Next,
modifier: Modifier = Modifier,
onOrgUnitActionCLicked: () -> Unit,
) {
BasicTextInput(
title = title,
state = state,
supportingText = supportingText,
legendData = legendData,
inputText = inputText,
val inputValue by remember(inputText) { mutableStateOf(inputText) }

var deleteButtonIsVisible by remember(inputText) { mutableStateOf(!inputText.isNullOrEmpty() && state != InputShellState.DISABLED) }
val focusRequester = remember { FocusRequester() }

val primaryButton:
@Composable()
(() -> Unit)?
if (deleteButtonIsVisible) {
primaryButton = {
IconButton(
modifier = Modifier
.testTag("INPUT_ORG_UNIT_RESET_BUTTON")
.padding(Spacing.Spacing0),
icon = {
Icon(
imageVector = Icons.Outlined.Cancel,
contentDescription = "Reset Button",
)
},
onClick = {
onValueChanged?.invoke("")
deleteButtonIsVisible = false
focusRequester.requestFocus()
},
enabled = state != InputShellState.DISABLED,
)
}
} else {
primaryButton = {
IconButton(
modifier = Modifier
.testTag("INPUT_ORG_UNIT_DROPDOWN_BUTTON")
.padding(Spacing.Spacing0),
icon = {
Icon(
imageVector = Icons.Outlined.ArrowDropDown,
contentDescription = "Dropdown Button",
)
},
onClick = {
onOrgUnitActionCLicked.invoke()
focusRequester.requestFocus()
},
enabled = state != InputShellState.DISABLED,
)
}
}
InputShell(
modifier = modifier
.testTag("INPUT_ORG_UNIT")
.focusRequester(focusRequester),
isRequiredField = isRequiredField,
onNextClicked = onNextClicked,
onValueChanged = onValueChanged,
keyboardOptions = KeyboardOptions(imeAction = imeAction),
modifier = modifier,
testTag = "ORG_UNIT",
onFocusChanged = onFocusChanged,
actionButton = {
title = title,
primaryButton = primaryButton,
secondaryButton = {
SquareIconButton(
modifier = Modifier.testTag("ORG_UNIT_BUTTON"),
enabled = state != InputShellState.DISABLED,
Expand All @@ -63,8 +117,51 @@ fun InputOrgUnit(
contentDescription = "org_unit_icon",
)
},
onClick = onOrgUnitActionCLicked,
onClick = {
onOrgUnitActionCLicked.invoke()
focusRequester.requestFocus()
},
)
},
state = state,
legend = {
legendData?.let {
Legend(legendData, Modifier.testTag("INPUT_ORG_UNIT_LEGEND"))
}
},
supportingText = {
supportingText?.forEach { label ->
SupportingText(
label.text,
label.state,
modifier = Modifier.testTag("INPUT_ORG_UNIT_SUPPORTING_TEXT"),
)
}
},
inputField = {
Box {
Text(
modifier = Modifier.testTag("INPUT_DROPDOWN_TEXT").fillMaxWidth(),
text = inputValue ?: "",
style = MaterialTheme.typography.bodyLarge.copy(
color = if (state != InputShellState.DISABLED) {
TextColor.OnSurface
} else {
TextColor.OnDisabledSurface
},
),
)
Box(
modifier = Modifier
.matchParentSize()
.alpha(0f)
.clickable(onClick = {
onOrgUnitActionCLicked.invoke()
focusRequester.requestFocus()
}),
)
}
},
onFocusChanged = onFocusChanged,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor
import org.junit.Rule
import org.junit.Test
Expand All @@ -37,7 +34,7 @@ class InputOrgUnitTest {
}

@Test
fun shouldAllowUserInputWhenEnabled() {
fun shouldDisplayDropdownButtonWhenEmpty() {
rule.setContent {
var inputValue by rememberSaveable { mutableStateOf("") }
InputOrgUnit(
Expand All @@ -52,42 +49,46 @@ class InputOrgUnitTest {
)
}
rule.onNodeWithTag("INPUT_ORG_UNIT").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").performTextInput("PHC fake")
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").assert(hasText("PHC fake"))
rule.onNodeWithTag("ORG_UNIT_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_DROPDOWN_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_DROPDOWN_BUTTON").assertIsEnabled()
}

@Test
fun shouldNotAllowUserInputWhenDisabled() {
fun shouldDisplayResetButtonWhenNotEmpty() {
rule.setContent {
var inputValue by rememberSaveable { mutableStateOf("Sample data") }
InputOrgUnit(
title = "Label",
state = InputShellState.DISABLED,
inputText = inputValue,
onValueChanged = {
if (it != null) {
inputValue = it
}
},
onOrgUnitActionCLicked = {},
)
}
rule.onNodeWithTag("INPUT_ORG_UNIT").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").assertIsNotEnabled()
rule.onNodeWithTag("ORG_UNIT_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").assertIsEnabled()
}

@Test
fun shouldShowResetButtonWhenTextFieldHasContent() {
fun shouldBeClickableIfDisabled() {
rule.setContent {
var inputValue by rememberSaveable { mutableStateOf("") }
InputOrgUnit(
title = "Label",
inputText = inputValue,
onValueChanged = {
if (it != null) {
inputValue = it
}
},
state = InputShellState.DISABLED,
onOrgUnitActionCLicked = {},
)
}
rule.onNodeWithTag("INPUT_ORG_UNIT").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").performTextInput("PHC fake")
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").assertExists()
rule.onNodeWithTag("ORG_UNIT_BUTTON").assertExists()
rule.onNodeWithTag("ORG_UNIT_BUTTON").assertIsNotEnabled()
rule.onNodeWithTag("INPUT_ORG_UNIT_DROPDOWN_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_DROPDOWN_BUTTON").assertIsNotEnabled()
}

@Test
Expand All @@ -109,7 +110,7 @@ class InputOrgUnitTest {
rule.onNodeWithTag("INPUT_ORG_UNIT").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").assertExists()
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").performClick()
rule.onNodeWithTag("INPUT_ORG_UNIT_FIELD").assertTextEquals("")
rule.onNodeWithTag("INPUT_DROPDOWN_TEXT").assertTextEquals("")
rule.onNodeWithTag("INPUT_ORG_UNIT_RESET_BUTTON").assertDoesNotExist()
}

Expand Down

0 comments on commit 9c13cf3

Please sign in to comment.