Skip to content

Commit

Permalink
Merge pull request #3725 from dhis2/release/3.0.0.2
Browse files Browse the repository at this point in the history
Release/3.0.0.2
  • Loading branch information
andresmr authored Jul 11, 2024
2 parents 385eadc + 008aeb9 commit a897212
Show file tree
Hide file tree
Showing 16 changed files with 251 additions and 148 deletions.
18 changes: 14 additions & 4 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
# Release notes - Android App for DHIS2 - 3.0.0.1
# Release notes - Android App for DHIS2 - 3.0.0.2

### Bug

[ANDROAPP-6194](https://dhis2.atlassian.net/browse/ANDROAPP-6194) Unable to search outside the program
[ANDROAPP-5869](https://dhis2.atlassian.net/browse/ANDROAPP-5869) IllegalArgumentException: Key "" was already used. If you are using LazyColumn/Row please make sure you provide a unique ke...

[ANDROAPP-6195](https://dhis2.atlassian.net/browse/ANDROAPP-6195) Missing terms in transifex
[ANDROAPP-6093](https://dhis2.atlassian.net/browse/ANDROAPP-6093) App crash when a catCombo is override

[ANDROAPP-6210](https://dhis2.atlassian.net/browse/ANDROAPP-6210) UninitializedPropertyAccessException on breaking the glass
[ANDROAPP-6104](https://dhis2.atlassian.net/browse/ANDROAPP-6104) Future date can be entered in Date of birth search field

[ANDROAPP-6124](https://dhis2.atlassian.net/browse/ANDROAPP-6124) Phone number input value type lacks of support for international symbols like \+, \(, \)

[ANDROAPP-6225](https://dhis2.atlassian.net/browse/ANDROAPP-6225) RuntimeException: Unable to start activity ComponentInfo\{com.dhis2/org.dhis2.usescases.searchTrackEntity.SearchTEAc...

[ANDROAPP-6271](https://dhis2.atlassian.net/browse/ANDROAPP-6271) IllegalArgumentException: The provided start date year \(2026\) is out of the years range of 2024..2024.

[ANDROAPP-6285](https://dhis2.atlassian.net/browse/ANDROAPP-6285) Maps - App crashes when navigating from home to maps but not from analytics to maps

[ANDROAPP-6305](https://dhis2.atlassian.net/browse/ANDROAPP-6305) Value of a TEA of valuetype AGE/DATE is not fully validated \(it is possible to add wrong dates\), and it breaks the analytics.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.dhis2.data.forms.dataentry.tablefields.spinner.SpinnerViewModel
import org.dhis2.form.model.ValueStoreResult.ERROR_UPDATING_VALUE
import org.dhis2.form.model.ValueStoreResult.VALUE_CHANGED
import org.dhis2.form.model.ValueStoreResult.VALUE_HAS_NOT_CHANGED
import org.dhis2.usescases.datasets.dataSetTable.dataSetSection.TableDataToTableModelMapper.Companion.INDICATORS_TABLE_ID
import org.hisp.dhis.android.core.arch.helpers.Result
import org.hisp.dhis.android.core.common.ValueType
import org.hisp.dhis.android.core.dataelement.DataElement
Expand Down Expand Up @@ -109,10 +110,12 @@ class DataValuePresenter(
val updatedTableModel = mapper(tableData)

val updatedTables = screenState.value.tables.map { tableModel ->
if (tableModel.id == catComboUid) {
updatedTableModel.copy(overwrittenValues = tableModel.overwrittenValues)
} else {
indicatorTables() ?: tableModel
when (tableModel.id) {
catComboUid -> updatedTableModel.copy(
overwrittenValues = tableModel.overwrittenValues,
)
INDICATORS_TABLE_ID -> indicatorTables() ?: tableModel
else -> tableModel
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import io.reactivex.Single
import org.dhis2.bindings.decimalFormat
import org.dhis2.commons.bindings.dataValueConflicts
import org.dhis2.commons.data.tuples.Pair
import org.dhis2.commons.date.DateUtils
import org.dhis2.composetable.model.TableCell
import org.dhis2.data.dhislogic.AUTH_DATAVALUE_ADD
import org.dhis2.data.forms.dataentry.tablefields.FieldViewModel
import org.dhis2.data.forms.dataentry.tablefields.FieldViewModelFactoryImpl
import org.dhis2.data.forms.dataentry.tablefields.spinner.SpinnerViewModel
import org.dhis2.usescases.datasets.dataSetTable.DataSetTableModel
import org.dhis2.utils.DateUtils
import org.hisp.dhis.android.core.D2
import org.hisp.dhis.android.core.arch.helpers.UidsHelper
import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope
Expand Down Expand Up @@ -61,6 +61,7 @@ class DataValueRepository(
?.categoryComboUid()
}?.distinct()
}

else -> {
val dataElementsSectionUid = d2.dataSetModule().sections().withDataElements()
.byDataSetUid().eq(dataSetUid)
Expand Down Expand Up @@ -157,29 +158,16 @@ class DataValueRepository(
dataElement: DataElement,
override: List<DataSetElement>?,
): DataElement {
return override
?.firstOrNull {
it.dataElement().uid() == dataElement.uid() && it.categoryCombo() != null
}?.let {
DataElement.builder()
.uid(dataElement.uid())
.code(dataElement.code())
.name(dataElement.name())
.displayName(dataElement.displayName())
.shortName(dataElement.shortName())
.displayShortName(dataElement.displayShortName())
.description(dataElement.description())
.displayDescription(dataElement.displayDescription())
.valueType(dataElement.valueType())
.zeroIsSignificant(dataElement.zeroIsSignificant())
.aggregationType(dataElement.aggregationType())
.formName(dataElement.formName())
.domainType(dataElement.domainType())
.displayFormName(dataElement.displayFormName())
.optionSet(dataElement.optionSet())
.categoryCombo(it.categoryCombo()).build()
}
?: dataElement
val dataSetElement = override?.firstOrNull {
it.dataElement().uid() == dataElement.uid() && it.categoryCombo() != null
}
return if (dataSetElement != null) {
dataElement.toBuilder()
.categoryCombo(dataSetElement.categoryCombo())
.build()
} else {
dataElement
}
}

private fun getDataValues(): Flowable<List<DataSetTableModel>> {
Expand Down Expand Up @@ -290,6 +278,7 @@ class DataValueRepository(
.get()
.map { section -> section.greyedFields() }
.toFlowable()

else -> Flowable.just(ArrayList())
}

Expand Down Expand Up @@ -319,45 +308,38 @@ class DataValueRepository(

private fun getDataElements(categoryCombo: CategoryCombo): Flowable<List<DataElement>> {
return if (sectionUid != "NO_SECTION") {
val listDataElements =
d2.dataSetModule().sections().withDataElements().byDataSetUid().eq(dataSetUid)
.uid(sectionUid).blockingGet()?.dataElements()
val dataElementsOverride: MutableList<DataElement> =
ArrayList()
val dataSetElements =
d2.dataSetModule().dataSets().withDataSetElements().uid(dataSetUid).blockingGet()
?.dataSetElements()
listDataElements
?.map { transformDataElement(it, dataSetElements) }
?.filter { it.categoryComboUid() == categoryCombo.uid() }
?.forEach { dataElementsOverride.add(it) }
val dataElementsInSection = d2.dataSetModule().sections().withDataElements()
.byDataSetUid().eq(dataSetUid)
.uid(sectionUid)
.blockingGet()
?.dataElements()

val dataSetElements = d2.dataSetModule().dataSets().withDataSetElements()
.uid(dataSetUid)
.blockingGet()
?.dataSetElements()

Flowable.just(
dataElementsOverride,
dataElementsInSection
?.map { transformDataElement(it, dataSetElements) }
?.filter { it.categoryComboUid() == categoryCombo.uid() },
)
} else {
val dataElementUids: MutableList<String> =
ArrayList()
val dataSetElements =
d2.dataSetModule().dataSets().withDataSetElements().byUid().eq(dataSetUid).one()
.blockingGet()?.dataSetElements()
for (dataSetElement in dataSetElements!!) {
if (dataSetElement.categoryCombo() != null &&
categoryCombo.uid() == dataSetElement.categoryCombo()!!.uid()
) {
dataElementUids.add(dataSetElement.dataElement().uid())
} else {
val uid = d2.dataElementModule().dataElements()
.uid(dataSetElement.dataElement().uid()).blockingGet()?.categoryComboUid()
if (categoryCombo.uid() == uid) {
dataElementUids.add(dataSetElement.dataElement().uid())
}
}
}
d2.dataElementModule().dataElements()
.byUid().`in`(dataElementUids)
val dataSetElementsInDataset =
d2.dataSetModule().dataSets().withDataSetElements()
.uid(dataSetUid)
.blockingGet()
?.dataSetElements()

val dataElements = d2.dataElementModule().dataElements()
.byUid().`in`(dataSetElementsInDataset?.map { it.dataElement().uid() })
.orderByName(RepositoryScope.OrderByDirection.ASC)
.get().toFlowable()
.blockingGet()

Flowable.just(
dataElements.map { transformDataElement(it, dataSetElementsInDataset) }
.filter { it.categoryComboUid() == categoryCombo.uid() },
)
}
}

Expand Down Expand Up @@ -403,6 +385,7 @@ class DataValueRepository(
.blockingIsEmpty()
hasDataValueAuthority && canWriteCatOption && canWriteOrgUnit
}

else -> Flowable.just(false)
}
}
Expand Down Expand Up @@ -490,35 +473,13 @@ class DataValueRepository(
}

fun getDataTableModel(categoryCombo: CategoryCombo): Observable<DataTableModel> {
return Flowable.zip<
List<DataElement>,
Map<String, List<List<Pair<CategoryOption, Category>>>>,
List<DataSetTableModel>,
List<DataElementOperand>,
List<DataElementOperand>,
DataTableModel,
>(
return Flowable.zip(
getDataElements(categoryCombo),
getCatOptions(categoryCombo.uid()),
getDataValues(),
getGreyFields(),
getCompulsoryDataElements(),
) { dataElements: List<DataElement>,
optionsWithCategory: Map<
String,
List<
List<
Pair<
CategoryOption,
Category,
>,
>,
>,
>,
dataValues: List<DataSetTableModel>,
disabledDataElements: List<DataElementOperand>,
compulsoryCells: List<DataElementOperand>,
->
) { dataElements, optionsWithCategory, dataValues, disabledDataElements, compulsoryCells ->
var options: List<List<String>> = ArrayList()
for ((_, value) in optionsWithCategory) {
options = getCatOptionCombos(value, 0, ArrayList(), null)
Expand Down Expand Up @@ -663,7 +624,7 @@ class DataValueRepository(
.byDataElementUid().eq(dataElement.uid())
.byCategoryOptionComboUid().eq(categoryOptionCombo.uid())
.blockingGet()
?.find { it.dataElement() == dataElement.uid() }
.find { it.dataElement() == dataElement.uid() }
?.syncState()

val conflictInField =
Expand All @@ -672,6 +633,7 @@ class DataValueRepository(
State.ERROR,
State.WARNING,
-> true

else -> false
}
}?.filter {
Expand All @@ -685,17 +647,21 @@ class DataValueRepository(
conflictInField != null &&
error != null ->
conflictInField + listOf(error)

valueStateSyncState == State.ERROR && conflictInField != null ->
conflictInField

error != null ->
listOf(error)

else -> null
}

val warningList = when {
valueStateSyncState == State.WARNING &&
conflictInField != null ->
conflictInField

else ->
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,14 @@ class TableDataToTableModelMapper(val mapFieldValueToUser: MapFieldValueToUser)
}

return TableModel(
id = "indicators",
id = INDICATORS_TABLE_ID,
title = mapFieldValueToUser.resources.getString(R.string.dashboard_indicators),
tableHeaderModel = tableHeader,
tableRows = tableRows,
)
}

companion object {
const val INDICATORS_TABLE_ID = "indicators"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,27 @@ class SearchRepositoryImplKt(
searchParametersModel: SearchParametersModel,
isOnline: Boolean,
): TrackedEntitySearchCollectionRepository {
var allowCache = false

if (searchParametersModel != searchRepositoryJava.savedSearchParameters || !FilterManager.getInstance()
.sameFilters(searchRepositoryJava.savedFilters)
) {
trackedEntityInstanceQuery =
searchRepositoryJava.getFilteredRepository(searchParametersModel)
} else {
trackedEntityInstanceQuery =
searchRepositoryJava.getFilteredRepository(searchParametersModel)
allowCache = true
}

if (searchRepositoryJava.fetchedTeiUIDs.isNotEmpty() && searchParametersModel.selectedProgram == null) {
trackedEntityInstanceQuery =
trackedEntityInstanceQuery.excludeUids().`in`(searchRepositoryJava.fetchedTeiUIDs.toList())
val allowCache = !(
searchParametersModel != searchRepositoryJava.savedSearchParameters ||
!FilterManager.getInstance().sameFilters(searchRepositoryJava.savedFilters)
)

if (
searchRepositoryJava.fetchedTeiUIDs.isNotEmpty() &&
searchParametersModel.selectedProgram == null
) {
trackedEntityInstanceQuery = trackedEntityInstanceQuery.excludeUids()
.`in`(searchRepositoryJava.fetchedTeiUIDs.toList())
}

val pagerFlow = if (isOnline && FilterManager.getInstance().stateFilters.isEmpty()) {
return if (isOnline && FilterManager.getInstance().stateFilters.isEmpty()) {
trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineFirst()
} else {
trackedEntityInstanceQuery.allowOnlineCache().eq(allowCache).offlineOnly()
}

return pagerFlow
}

override suspend fun searchParameters(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ private void initSearchParameters() {
uid,
selectedOrgUnit,
ValueType.ORGANISATION_UNIT,
null
null,
true
)
);
return Unit.INSTANCE;
Expand Down Expand Up @@ -397,7 +398,6 @@ private void configureBottomNavigation() {
this,
() -> {
presenter.trackSearchMapVisualization();
viewModel.setMapScreen();
showMap();
showSearchAndFilterButtons();
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class SearchTEMap : FragmentGlobalAbstract(), MapboxMap.OnMapClickListener {
(context as SearchTEActivity).searchComponent.plus(
SearchTEMapModule(),
).inject(this)
viewModel.setMapScreen()
}

override fun onCreateView(
Expand Down
Loading

0 comments on commit a897212

Please sign in to comment.