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 5893 implement org unit tree in org unit component #3672

Closed
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
@@ -1,24 +1,16 @@
package org.dhis2.common.filters

import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.TypeTextAction
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.PickerActions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId
import org.dhis2.R
import org.dhis2.common.BaseRobot
import org.dhis2.common.matchers.DatePickerMatchers.Companion.matchesDate
import org.dhis2.commons.filters.FilterHolder
import org.dhis2.ui.dialogs.orgunit.DONE_TEST_TAG
import org.dhis2.ui.dialogs.orgunit.ITEM_CHECK_TEST_TAG
import org.dhis2.ui.dialogs.orgunit.ITEM_TEST_TAG

fun filterRobotCommon(robotBody: FiltersRobot.() -> Unit) {
FiltersRobot().apply {
Expand Down Expand Up @@ -56,7 +48,7 @@ class FiltersRobot : BaseRobot() {
}

fun selectNotSyncedState() {
onView( withId(R.id.stateNotSynced)).perform(click())
onView(withId(R.id.stateNotSynced)).perform(click())
}

fun acceptDateSelected() {
Expand All @@ -66,6 +58,4 @@ class FiltersRobot : BaseRobot() {
fun checkDate(year: Int, monthOfYear: Int, dayOfMonth: Int) {
onView(withId(R.id.datePicker)).check(matches(matchesDate(year, monthOfYear, dayOfMonth)))
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package org.dhis2.usescases.orgunitselector

import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import org.dhis2.common.BaseRobot
import org.dhis2.ui.dialogs.orgunit.DONE_TEST_TAG
import org.dhis2.ui.dialogs.orgunit.ITEM_CHECK_TEST_TAG

fun orgUnitSelectorRobot(
composeTestRule: ComposeTestRule,
Expand All @@ -19,9 +18,9 @@ fun orgUnitSelectorRobot(

class OrgUnitSelectorRobot(private val composeTestRule: ComposeTestRule) : BaseRobot() {
fun selectTreeOrgUnit(orgUnitName: String) {
composeTestRule.onNodeWithTag("$ITEM_CHECK_TEST_TAG$orgUnitName")
composeTestRule.onNodeWithTag("ORG_TREE_ITEM_$orgUnitName")
.performScrollTo()
.performClick()
composeTestRule.onNodeWithTag(DONE_TEST_TAG).performClick()
composeTestRule.onNodeWithText("Done").performClick()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package org.dhis2.usescases.teidashboard.dialogs.scheduling

import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
Expand Down Expand Up @@ -110,6 +114,7 @@ class SchedulingDialogUiTest {
composeTestRule.onNodeWithText("Done").assertExists()
}

@OptIn(ExperimentalTestApi::class)
@Test
fun selectProgramStage() {
val programStages = listOf(
Expand All @@ -126,7 +131,8 @@ class SchedulingDialogUiTest {
}
}

composeTestRule.onNodeWithText("Program stage").performClick()
composeTestRule.onAllNodesWithTag("INPUT_DROPDOWN").onFirst().performClick()
composeTestRule.waitUntilExactlyOneExists(hasTestTag("INPUT_DROPDOWN_MENU_ITEM_1"))
composeTestRule.onNodeWithTag("INPUT_DROPDOWN_MENU_ITEM_1").performClick()

verify(viewModel).updateStage(programStages[1])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,6 @@ class DataSetSectionFragment : FragmentGlobalAbstract(), DataValueContract.View
updateCellValue: (TableCell) -> Unit,
) {
OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.withPreselectedOrgUnits(cell.value?.let { listOf(it) } ?: emptyList())
.onSelection { selectedOrgUnits ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ public void updateFilters(int totalFilters) {
@Override
public void openOrgUnitTreeSelector() {
new OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(FilterManager.getInstance().getOrgUnitUidsFilters())
.onSelection(selectedOrgUnits -> {
presenter.setOrgUnitFilters((List<OrganisationUnit>) selectedOrgUnits);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ public void showOrgUnitDialog(List<OrganisationUnit> data) {
preselectedOrgUnits.add(selectedOrgUnit.uid());
}
new OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.withPreselectedOrgUnits(preselectedOrgUnits)
.orgUnitScope(new OrgUnitSelectorScope.DataSetCaptureScope(dataSetUid))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,6 @@ class EventDetailsFragment : FragmentGlobalAbstract() {

private fun showOrgUnitDialog() {
OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(
viewModel.eventOrgUnit.value.selectedOrgUnit
?.let { listOf(it.uid()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ class ProgramFragment : FragmentGlobalAbstract(), ProgramView {

override fun openOrgUnitTreeSelector() {
OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(
FilterManager.getInstance().orgUnitFilters.map { it.uid() }.toMutableList(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ class ProgramEventDetailActivity :
override fun selectOrgUnitForNewEvent() {
enableAddEventButton(false)
OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.orgUnitScope(
OrgUnitSelectorScope.ProgramCaptureScope(programUid),
Expand Down Expand Up @@ -373,7 +372,6 @@ class ProgramEventDetailActivity :

override fun openOrgUnitTreeSelector() {
OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(FilterManager.getInstance().orgUnitUidsFilters)
.onSelection { selectedOrgUnits ->
presenter.setOrgUnitFilters(selectedOrgUnits)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ class ProgramStageSelectionActivity : ActivityGlobalAbstract(), ProgramStageSele
enrollmentUid: String?,
) {
OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.orgUnitScope(
OrgUnitSelectorScope.ProgramCaptureScope(programUid),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ private void initSearchParameters() {
resourceManager,
(uid, preselectedOrgUnits, orgUnitScope, label) -> {
new OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(preselectedOrgUnits)
.singleSelection()
.onSelection(selectedOrgUnits -> {
Expand Down Expand Up @@ -649,7 +648,6 @@ public void clearFilters() {
@Override
public void openOrgUnitTreeSelector() {
new OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(
FilterManager.getInstance().getOrgUnitUidsFilters()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ public void enroll(String programUid, String uid, HashMap<String, String> queryD
allOrgUnits -> {
if (allOrgUnits.size() > 1) {
new OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.onSelection(selectedOrgUnits -> {
if (!selectedOrgUnits.isEmpty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ class IndicatorsFragment : FragmentGlobalAbstract(), IndicatorsView {
lineListingColumnId: Int?,
) {
OUTreeFragment.Builder()
.showAsDialog()
.withPreselectedOrgUnits(
chartModel.graph.orgUnitsSelected(lineListingColumnId).toMutableList(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ class TEIDataFragment : FragmentGlobalAbstract(), TEIDataContracts.View {

override fun displayOrgUnitSelectorForNewEvent(programUid: String, programStageUid: String) {
OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.orgUnitScope(
OrgUnitSelectorScope.ProgramCaptureScope(programUid),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ private void handleCalendarResult(
public void enroll(String programUid, String uid) {
selectedEnrollmentDate = Calendar.getInstance().getTime();
OUTreeFragment orgUnitDialog = new OUTreeFragment.Builder()
.showAsDialog()
.singleSelection()
.onSelection(selectedOrgUnits -> {
if (!selectedOrgUnits.isEmpty())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
package org.dhis2.commons.orgunitselector

import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Point
import android.os.Build
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.DialogFragment
import androidx.compose.ui.res.stringResource
import androidx.fragment.app.viewModels
import com.google.accompanist.themeadapter.material3.Mdc3Theme
import org.dhis2.ui.dialogs.orgunit.OrgUnitSelectorActions
import org.dhis2.ui.dialogs.orgunit.OrgUnitSelectorDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.dhis2.commons.R
import org.hisp.dhis.android.core.organisationunit.OrganisationUnit
import org.hisp.dhis.mobile.ui.designsystem.component.OrgBottomSheet
import javax.inject.Inject

const val ARG_SHOW_AS_DIALOG = "OUTreeFragment.ARG_SHOW_AS_DIALOG"
const val ARG_SINGLE_SELECTION = "OUTreeFragment.ARG_SINGLE_SELECTION"
const val ARG_SCOPE = "OUTreeFragment.ARG_SCOPE"
const val ARG_PRE_SELECTED_OU = "OUTreeFragment.ARG_PRE_SELECTED_OU"

class OUTreeFragment private constructor() : DialogFragment() {
class OUTreeFragment private constructor() : BottomSheetDialogFragment() {

class Builder {
private var showAsDialog = false
private var preselectedOrgUnits = listOf<String>()
private var singleSelection = false
private var selectionListener: ((selectedOrgUnits: List<OrganisationUnit>) -> Unit) = {}
private var orgUnitScope: OrgUnitSelectorScope = OrgUnitSelectorScope.UserSearchScope()
fun showAsDialog() = apply {
showAsDialog = true
}

fun withPreselectedOrgUnits(preselectedOrgUnits: List<String>) = apply {
if (singleSelection && preselectedOrgUnits.size > 1) {
Expand Down Expand Up @@ -70,7 +61,6 @@ class OUTreeFragment private constructor() : DialogFragment() {
return OUTreeFragment().apply {
selectionCallback = selectionListener
arguments = Bundle().apply {
putBoolean(ARG_SHOW_AS_DIALOG, showAsDialog)
putBoolean(ARG_SINGLE_SELECTION, singleSelection)
putParcelable(ARG_SCOPE, orgUnitScope)
putStringArrayList(ARG_PRE_SELECTED_OU, ArrayList(preselectedOrgUnits))
Expand Down Expand Up @@ -108,17 +98,9 @@ class OUTreeFragment private constructor() : DialogFragment() {
)?.inject(this)
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.window!!.setBackgroundDrawableResource(android.R.color.transparent)
return dialog
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
showAsDialog().let { showAsDialog ->
showsDialog = showAsDialog
}
setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme)
}

override fun onCreateView(
Expand All @@ -129,41 +111,21 @@ class OUTreeFragment private constructor() : DialogFragment() {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
Mdc3Theme {
val list by presenter.treeNodes.collectAsState()
OrgUnitSelectorDialog(
title = null,
items = list,
actions = object : OrgUnitSelectorActions {
override val onSearch: (String) -> Unit
get() = presenter::searchByName
override val onOrgUnitChecked:
(orgUnitUid: String, isChecked: Boolean) -> Unit
get() = presenter::onOrgUnitCheckChanged
override val onOpenOrgUnit: (orgUnitUid: String) -> Unit
get() = presenter::onOpenChildren
override val onDoneClick: () -> Unit
get() = this@OUTreeFragment::confirmOuSelection
override val onCancelClick: () -> Unit
get() = this@OUTreeFragment::cancelOuSelection
override val onClearClick: () -> Unit
get() = presenter::clearAll
},
)
}
val list by presenter.treeNodes.collectAsState()
OrgBottomSheet(
clearAllButtonText = stringResource(id = R.string.action_clear_all),
orgTreeItems = list,
onSearch = presenter::searchByName,
onDismiss = { cancelOuSelection() },
onItemClick = presenter::onOpenChildren,
onItemSelected = presenter::onOrgUnitCheckChanged,
onClearAll = presenter::clearAll,
onDone = { confirmOuSelection() },
)
}
}
}

override fun onResume() {
super.onResume()
showAsDialog().takeIf { it }?.let {
fixDialogSize(0.9, 0.9)
}
}

private fun showAsDialog() = arguments?.getBoolean(ARG_SHOW_AS_DIALOG, false) ?: false

private fun confirmOuSelection() {
selectionCallback(presenter.getOrgUnits())
exitOuSelection()
Expand All @@ -175,25 +137,6 @@ class OUTreeFragment private constructor() : DialogFragment() {
}

private fun exitOuSelection() {
if (showAsDialog()) {
dismiss()
} else {
activity?.apply {
setResult(Activity.RESULT_OK)
finish()
}
}
}
}

fun DialogFragment.fixDialogSize(widthPercent: Double, heightPercent: Double) {
val size = Point()
dialog?.window?.apply {
windowManager.defaultDisplay.getSize(size)

setLayout(widthPercent of size.x, heightPercent of size.y)
setGravity(Gravity.CENTER)
dismiss()
}
}

private infix fun Double.of(value: Int) = (this * value).toInt()
Loading
Loading