Skip to content

Commit

Permalink
Merge pull request #1732 from dhis2/release/2.3
Browse files Browse the repository at this point in the history
feat: v2.3 release
  • Loading branch information
Balcan committed Oct 19, 2020
2 parents 4a50136 + dd98e93 commit 4981339
Show file tree
Hide file tree
Showing 403 changed files with 12,612 additions and 4,768 deletions.
101 changes: 77 additions & 24 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,92 @@
Android Capture App for DHIS 2 (v2.2.2) - Patch version
Android Capture App for DHIS 2 (v2.3)

<table>
<tbody>
<tr>
<td>
<img src="https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/android-chrome-384x384.png" width="800">
</td>
<td>This is a patch version of the <strong>DHIS2 Android App</strong> It builds upon the last version including bug fixes that couldn't wait to the next version. It includes no functional improvements neither changes in the User Interface. It means that yours users can update without experiencing any change in the UI.
<td>The new <strong>DHIS2 Android App</strong> allows offline data capture across all DHIS2 data models. Data and metadata are automatically synchronized whenever there is internet access, always keeping the most relevant data for the logged user in the device.
The app is compatible and we support <strong>2.35</strong>, <strong>2.34</strong>, <strong>2.33</strong>. And has no breaking changes with <strong>2.32</strong>, <strong>2.31</strong>, <strong>2.30</strong> and <strong>2.29</strong>.
</td>
</tr>
<tr>
<td colspan="2" bgcolor="white">

## Bugs fixed
**[ANDROAPP-3277](https://jira.dhis2.org/browse/ANDROAPP-3277) Calculated values not working
**[ANDROAPP-3253](https://jira.dhis2.org/browse/ANDROAPP-3287) Sync error log sharing selects several items
**[ANDROAPP-3270](https://jira.dhis2.org/browse/ANDROAPP-3256) Reduce number of API search requests
**[ANDROAPP-3259](https://jira.dhis2.org/browse/ANDROAPP-3296) Org. Unit tree selector not handling selection correctly
**[ANDROAPP-3257](https://jira.dhis2.org/browse/ANDROAPP-3308) Fixed crash when using event date sorting
**[ANDROAPP-3254](https://jira.dhis2.org/browse/ANDROAPP-3095) Option sets behave different when there is search box or not
**[ANDROAPP-3254](https://jira.dhis2.org/browse/ANDROAPP-3276) User is able to schedule event regardless 'Hide due date' configuration
**[ANDROAPP-3250](https://jira.dhis2.org/browse/ANDROAPP-3295) Cannot use Calculated Values variables in rule engine actions
**[ANDROAPP-3264](https://jira.dhis2.org/browse/ANDROAPP-3116) Fix note badge color when tab is not selected
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-2669) Icons in the event list top menu do not change color
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3275) Indicator name is not always displayed
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3160) Tab labels not showing when opening dashboard
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3274) User is not forced to search before creating new enrollment
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3227) Fix backdrop rounded corners
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3033) Open second section if first one is hidden
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3232) Updating event date deletes OU information
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3306) Percentage indicator is not consistent
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3307) No action when using "reset search" button
**[ANDROAPP-3258](https://jira.dhis2.org/browse/ANDROAPP-3309) Mandatory fields message hides 'save' button in data sets

You can find in Jira details on the [bugs fixed](https://jira.dhis2.org/issues/?filter=11898) in this version.
## GENERIC FEATURES

**Add option to clear URL in login screen:** In the previous version the user could easily clear the username or password, but not the URL. A button to clear the text from the URL text box has been added to facilitate the login process.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-3315) | [Screenshot](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/Log+In.png)

**Improve error information to the user:** In this version the app renders the name of the data elements or attributes which fail in the synchronization process and replace it in the error message by the name of the data element or the attribute. In addition, the app displays an error message also inside the data entry form, next to the affected field. This helps the user identify the source of error and fix the problem.

[Jira ](https://jira.dhis2.org/browse/ANDROAPP-2778) | [Jira 2 ](https://jira.dhis2.org/browse/ANDROAPP-3272) | [Screenshot](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/Error+message.png)

**Improve feedback when form rendering is slow:** A loading bar has been added in the data entry forms when form or section are loading and when programs rules are executed

[Jira ](https://jira.dhis2.org/browse/ANDROAPP-3026)



**Open Image clicking on it:** When the user taps on an image, the image is opened and displayed on the screen taking the whole screen.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-2834) | [Screenshot](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/Picture+Display.png)



## USER EXPERIENCE AND USER INTERFACE
**New Event Cards in Event and Tracker programs:** The event and TEI cards have been improved and made more intuitive and informative in the last version. We have harmonised our user interface and brought this design to the lists of events in event programs and in the TEI dashboard. The cards display the name of the attribute or data element next to the value for the first three marked to be displayed. It is also possible to expand the card to display the rest of the attributes or data elements, which are shown following the same format.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-2766) | [Screenshot 1](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/New+Event+Cards.png)

**New Fields for Data Entry form:** All value types rendering has been redefined. The images are fully displayed now with an adjusted size, the icons on the left side have been removed and the clear buttons have been added to all value types as well.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-2917) | [Screenshot](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/New+Entry+forms.png)


## DATA ENTRY
**Barcode/QR code to also accept keyboard data entry:** Barcode and QR code rendered fields will also accept manual data entry of the codified text.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-3086)

**Non-editable fields have different display:** Fields where the value is auto-complete, either because it is auto-generated or assigned by a program rule, are rendered greyed out giving information to the user about the field not being editable.

[Jira](https://jira.dhis2.org/browse/ANDROAPP-2848) | [Screenshot 1](https://s3-eu-west-1.amazonaws.com/content.dhis2.org/dhis2-android/release+notes+2.3/Non+Editable+fields.png)




## QUALITY / SECURITY / PERFORMANCE

[Functional Test][Event] Delete Event [Jira](https://jira.dhis2.org/browse/ANDROAPP-3200)

[Functional Test][Event] Details Event [Jira](https://jira.dhis2.org/browse/ANDROAPP-3201)

[Functional Test][Event] Share QR Event [Jira](https://jira.dhis2.org/browse/ANDROAPP-3202)

[Functional Test][Sync] Datasets [Jira](https://jira.dhis2.org/browse/ANDROAPP-2995)

[Functional Test][Sync] Event [Jira](https://jira.dhis2.org/browse/ANDROAPP-2997)

[Functional Test][Sync] Tei [Jira](https://jira.dhis2.org/browse/ANDROAPP-2996)

[Functional Test][Tei Dashboard] Enrollment [Jira](https://jira.dhis2.org/browse/ANDROAPP-3199)

[Test] Flow ui test [Jira](https://jira.dhis2.org/browse/ANDROAPP-3321)

[Performance][OrgUnitTree] Review list/adapter when loading org units [Jira](https://jira.dhis2.org/browse/ANDROAPP-2945)

Disable ADB in production version [Jira ](https://jira.dhis2.org/browse/ANDROAPP-2998)

Enable Acra in Prod and Debug [Jira](https://jira.dhis2.org/browse/ANDROAPP-3334)

Track socketTimeOut in firebase and show message [Jira](https://jira.dhis2.org/browse/ANDROAPP-2868)

Update crash activity texts [Jira](https://jira.dhis2.org/browse/ANDROAPP-3347)


You can find in Jira details on the [new features](https://jira.dhis2.org/issues/?filter=11918) and [bugs fixed](https://jira.dhis2.org/issues/?filter=11919) in this version.

Remember to check the [documentation](https://www.dhis2.org/android-documentation) for detailed information of the features included in the App and how to configure DHIS2 to use it.

Expand Down
19 changes: 10 additions & 9 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
includeAndroidResources = true
returnDefaultValues = true
}
animationsDisabled = true
}

lintOptions {
Expand Down Expand Up @@ -71,8 +72,6 @@ android {
unitTests.returnDefaultValues = true
}

configurations.all*.exclude module: 'jsr305'

packagingOptions {
// excluding duplicate license files
// from jackson modules
Expand Down Expand Up @@ -156,8 +155,8 @@ android {
sourceCompatibility = "8"
}

dataBinding {
enabled = true
buildFeatures {
dataBinding true
}

packagingOptions {
Expand Down Expand Up @@ -205,17 +204,19 @@ dependencies {
implementation project(':viewpagerdotsindicator')
implementation project(':tableview')

implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-rc02'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "androidx.multidex:multidex:${libraries.multidex}"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation "androidx.lifecycle:lifecycle-extensions:${libraries.lifecycle}"
implementation "androidx.work:work-runtime:2.2.0"
implementation "androidx.work:work-rxjava2:2.2.0"
implementation "androidx.exifinterface:exifinterface:1.2.0"

implementation 'com.google.code.findbugs:jsr305:3.0.1'

releaseImplementation("org.hisp.dhis:android-core:${libraries.dhis2sdk}") {
exclude group: "org.hisp.dhis", module: "core-rules"
Expand Down Expand Up @@ -294,8 +295,8 @@ dependencies {
implementation 'com.google.firebase:firebase-messaging:20.0.0'

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
implementation 'com.facebook.stetho:stetho:1.5.1'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'

//RXLint
Expand Down Expand Up @@ -335,7 +336,7 @@ dependencies {
//Test
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.test.espresso:espresso-idling-resource:3.2.0'

implementation 'androidx.test.espresso.idling:idling-concurrent:3.2.0'

testImplementation "androidx.arch.core:core-testing:2.0.0"
testImplementation "androidx.test:core:1.2.0"
Expand Down
3 changes: 2 additions & 1 deletion app/src/androidTest/java/org/dhis2/AppTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AppTest : App() {

@Override
override fun setUpServerComponent() {
D2Manager.setTestingDatabase(DB_TO_IMPORT, "android")
D2Manager.setTestingDatabase(DB_TO_IMPORT, USERNAME)
D2Manager.blockingInstantiateD2(ServerModule.getD2Configuration(this))

serverComponent = appComponent.plus(ServerModule())
Expand Down Expand Up @@ -52,5 +52,6 @@ class AppTest : App() {

companion object {
const val DB_TO_IMPORT = "127-0-0-1-8080_android_unencrypted.db"
const val USERNAME = "android"
}
}
6 changes: 6 additions & 0 deletions app/src/androidTest/java/org/dhis2/common/BaseRobot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import org.dhis2.R
import org.dhis2.usescases.main.MainActivity
import org.hamcrest.CoreMatchers.allOf

open class BaseRobot {
Expand Down Expand Up @@ -71,6 +73,10 @@ open class BaseRobot {
return visibleActivityName == T::class.java.name
}

fun <T : Activity> checkActivityIsFinishing(rule : ActivityTestRule<T>){
assert(rule.activity.isFinishing)
}

companion object {
const val TIMEOUT = 5000L
const val CONDITION_CHECK_INTERVAL = 200L
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.dhis2.common.idlingresources

import androidx.fragment.app.FragmentManager
import androidx.test.espresso.IdlingResource

class FragmentIdlingResource(
private val manager: FragmentManager,
private val tag: String) : IdlingResource {

private var resourceCallback: IdlingResource.ResourceCallback? = null

override fun getName() = "fragment idling resource"
override fun registerIdleTransitionCallback(
callback: IdlingResource.ResourceCallback?
) {
resourceCallback = callback
}

override fun isIdleNow(): Boolean {
val fragmentAbout = manager.findFragmentByTag(tag)

val idle = (fragmentAbout == null)
if (idle) {
resourceCallback?.onTransitionToIdle()
}
return idle
}
}
37 changes: 37 additions & 0 deletions app/src/androidTest/java/org/dhis2/common/rules/RetryRule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.dhis2.common.rules

import android.util.Log
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement

class RetryRule(val retryCount: Int = 3) : TestRule {

private val TAG = RetryRule::class.java.simpleName

override fun apply(base: Statement, description: Description): Statement {
return statement(base, description)
}

private fun statement(base: Statement, description: Description): Statement {
return object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
var caughtThrowable: Throwable? = null

for (i in 0 until retryCount) {
try {
base.evaluate()
return
} catch (t: Throwable) {
caughtThrowable = t
Log.e(TAG, description.displayName + ": run " + (i + 1) + " failed")
}
}

Log.e(TAG, description.displayName + ": giving up after " + retryCount + " failures")
throw caughtThrowable!!
}
}
}
}
10 changes: 10 additions & 0 deletions app/src/androidTest/java/org/dhis2/usescases/BaseTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.dhis2.common.preferences.PreferencesRobot
import org.dhis2.common.rules.DisableAnimations
import org.dhis2.utils.idlingresource.CountingIdlingResourceSingleton
import org.hisp.dhis.android.core.D2Manager
import org.hisp.dhis.android.core.arch.api.internal.ServerURLWrapper
import org.junit.After
import org.junit.Before
import org.junit.ClassRule
Expand Down Expand Up @@ -95,6 +96,14 @@ open class BaseTest {
}
}

fun turnOnConnectivityAfterLogin(){
ServerURLWrapper.setServerUrl("$MOCK_SERVER_URL/$API/")
}

fun turnOffConnectivityAfterLogin(){
ServerURLWrapper.setServerUrl("none")
}

private fun disableIntents() {
if (isIntentsEnable) {
Intents.release()
Expand Down Expand Up @@ -122,5 +131,6 @@ open class BaseTest {
@JvmField
val disableAnimationsTestRule = DisableAnimations()
const val MOCK_SERVER_URL = "http://127.0.0.1:8080"
const val API = "api"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package org.dhis2.usescases.about

import android.Manifest
import android.content.pm.PackageManager
import androidx.test.espresso.IdlingRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import org.dhis2.BuildConfig
import org.dhis2.R
import org.dhis2.common.idlingresources.FragmentIdlingResource
import org.dhis2.common.viewactions.waitForTransitionUntil
import org.dhis2.usescases.BaseTest
import org.dhis2.usescases.main.MainActivity
import org.dhis2.usescases.main.homeRobot
Expand All @@ -26,7 +29,6 @@ class AboutTest : BaseTest() {
@Test
fun shouldCheckVersionsWhenOpenAboutScreen() {
startActivity()

val appVersion = getAppVersionName()
val sdkVersion = getSDKVersionName()

Expand Down Expand Up @@ -56,4 +58,5 @@ class AboutTest : BaseTest() {

private fun getSDKVersionName() =
String.format(context.getString(R.string.about_sdk), BuildConfig.SDK_VERSION)

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class EnrollmentTest : BaseTest() {

private fun prepareSearchIntentAndLaunchActivity() {
Intent().apply {
putExtra(SearchTETest.CHILD_PROGRAM_UID, SearchTETest.CHILD_PROGRAM_UID_VALUE)
putExtra(SearchTETest.PROGRAM_UID, SearchTETest.CHILD_PROGRAM_UID_VALUE)
putExtra(SearchTETest.CHILD_TE_TYPE, SearchTETest.CHILD_TE_TYPE_VALUE)
}.also { ruleSearch.launchActivity(it) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ const val TEI_UID = "TEI_UID"
const val ENROLLMENT_UID = "ENROLLMENT_UID"
const val PROGRAM_STAGE_UID = "PROGRAM_STAGE_UID"


const val PROGRAM_TB_UID = "ur1Edk5Oe2n"
const val PROGRAM_XX_TRACKER_UID = "U5KybNCtA3E"
const val EVENT_DETAILS_UID = "oPCuUeDGaIu"
const val EVENT_TO_SHARE_UID = "y0xoVIzBpnL"
const val TEI_EVENT_TO_DELETE_UID = "foc5zag6gbE"
const val ENROLLMENT_EVENT_DELETE_UID = "SolDyMgW3oc"
const val PROGRAM_STAGE_TO_SHARE = "EPEcjy3FWmI"
const val TEI_TO_UPDATE_UID = "LxMVYhJm3Jp"
const val ENROLLMENT_TO_UPDATE_UID = "awZ5RHoJin5"

fun prepareEventDetailsIntentAndLaunchActivity(rule: ActivityTestRule<EventCaptureActivity>) {
Intent().apply {
Expand All @@ -43,3 +44,11 @@ fun prepareEventToShareIntentAndLaunchActivity(ruleEventDetail: ActivityTestRule
putExtra(PROGRAM_STAGE_UID, PROGRAM_STAGE_TO_SHARE)
}.also { ruleEventDetail.launchActivity(it) }
}

fun prepareEventToUpdateIntentAndLaunchActivity(ruleTeiDashboard: ActivityTestRule<TeiDashboardMobileActivity>) {
Intent().apply {
putExtra(PROGRAM_UID, PROGRAM_TB_UID)
putExtra(TEI_UID, TEI_TO_UPDATE_UID)
putExtra(ENROLLMENT_UID, ENROLLMENT_TO_UPDATE_UID)
}.also { ruleTeiDashboard.launchActivity(it) }
}

0 comments on commit 4981339

Please sign in to comment.