From 94eb1ce3205c46c108c3bef74b0a8daa21c0e7b8 Mon Sep 17 00:00:00 2001 From: Martin Ndegwa Date: Wed, 20 Mar 2024 23:06:43 +0300 Subject: [PATCH] Migrate FHIR Core to latest SDK Artifacts (#3159) * Upgrade FHIR SDK Artifacts * Upgrade 3rd party artifacts * Upgrade FHIR SDK Artifacts - Upgrade ticket #3155 Signed-off-by: Martin Ndegwa * Update gradle properties * Downgrade material 3 version --------- Signed-off-by: Martin Ndegwa --- android/build.gradle.kts | 7 +- .../buildSrc/src/main/kotlin/BuildConfigs.kt | 12 +++ android/engine/build.gradle.kts | 8 +- android/geowidget/build.gradle.kts | 8 +- android/gradle/libs.versions.toml | 36 +++++---- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/macrobenchmark/build.gradle.kts | 12 +-- android/quest/build.gradle.kts | 14 ++-- .../ui/questionnaire/QuestionnaireActivity.kt | 76 ++++++++++--------- .../questionnaire/QuestionnaireViewModel.kt | 2 +- .../QuestionnaireViewModelTest.kt | 51 +++++++------ 11 files changed, 121 insertions(+), 107 deletions(-) create mode 100644 android/buildSrc/src/main/kotlin/BuildConfigs.kt diff --git a/android/build.gradle.kts b/android/build.gradle.kts index ea86e50a19..75ea9794b3 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -58,18 +58,17 @@ subprojects { } configure { - val lintVersion = "0.49.0" kotlin { target("**/*.kt") - ktlint(lintVersion) + ktlint(BuildConfigs.ktLintVersion) ktfmt().googleStyle() licenseHeaderFile("${project.rootProject.projectDir}/license-header.txt") } kotlinGradle { target("*.gradle.kts") - ktlint(lintVersion) + ktlint(BuildConfigs.ktLintVersion) ktfmt().googleStyle() } @@ -91,7 +90,7 @@ subprojects { resolutionStrategy { eachDependency { when (requested.group) { - "org.jacoco" -> useVersion("0.8.11") + "org.jacoco" -> useVersion(BuildConfigs.jacocoVersion) } } } diff --git a/android/buildSrc/src/main/kotlin/BuildConfigs.kt b/android/buildSrc/src/main/kotlin/BuildConfigs.kt new file mode 100644 index 0000000000..b0121e19b3 --- /dev/null +++ b/android/buildSrc/src/main/kotlin/BuildConfigs.kt @@ -0,0 +1,12 @@ +object BuildConfigs { + const val minSdk = 26 + const val compileSdk = 34 + const val targetSdk = 34 + const val versionCode = 10 + const val versionName = "1.1.0" + const val applicationId = "org.smartregister.opensrp" + const val jvmToolchain = 17 + const val kotlinCompilerExtensionVersion = "1.5.8" + const val jacocoVersion ="0.8.11" + const val ktLintVersion = "0.49.0" +} \ No newline at end of file diff --git a/android/engine/build.gradle.kts b/android/engine/build.gradle.kts index d3f5f58fe7..b6dd4e0eff 100644 --- a/android/engine/build.gradle.kts +++ b/android/engine/build.gradle.kts @@ -15,12 +15,12 @@ plugins { } android { - compileSdk = 34 + compileSdk = BuildConfigs.compileSdk namespace = "org.smartregister.fhircore.engine" defaultConfig { - minSdk = 26 + minSdk = BuildConfigs.minSdk testInstrumentationRunner = "org.smartregister.fhircore.engine.EngineTestRunner" consumerProguardFiles("consumer-rules.pro") buildConfigField( @@ -62,7 +62,7 @@ android { dataBinding = true buildConfig = true } - composeOptions { kotlinCompilerExtensionVersion = "1.5.8" } + composeOptions { kotlinCompilerExtensionVersion = BuildConfigs.kotlinCompilerExtensionVersion } packaging { resources.excludes.addAll( @@ -100,7 +100,7 @@ android { lint { baseline = file("lint-baseline.xml") } - testCoverage { jacocoVersion = "0.8.11" } + testCoverage { jacocoVersion = BuildConfigs.jacocoVersion } } tasks.withType { diff --git a/android/geowidget/build.gradle.kts b/android/geowidget/build.gradle.kts index e7b2fdb091..0ad95063d1 100644 --- a/android/geowidget/build.gradle.kts +++ b/android/geowidget/build.gradle.kts @@ -14,12 +14,12 @@ plugins { } android { - compileSdk = 34 + compileSdk = BuildConfigs.compileSdk namespace = "org.smartregister.fhircore.geowidget" defaultConfig { - minSdk = 26 + minSdk = BuildConfigs.minSdk buildConfigField("String", "MAPBOX_SDK_TOKEN", """"${project.extra["MAPBOX_SDK_TOKEN"]}"""") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") @@ -58,7 +58,7 @@ android { buildConfig = true } - composeOptions { kotlinCompilerExtensionVersion = "1.5.8" } + composeOptions { kotlinCompilerExtensionVersion = BuildConfigs.kotlinCompilerExtensionVersion } packaging { resources.excludes.addAll( @@ -98,7 +98,7 @@ android { } } - testCoverage { jacocoVersion = "0.8.11" } + testCoverage { jacocoVersion = BuildConfigs.jacocoVersion } } tasks.withType { diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index a136b8bbb7..8392d430c6 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -8,28 +8,28 @@ commonsJexl3 = "3.2.1" compressor = "3.0.1" constraintlayout = "2.1.4" constraintlayout-compose = "1.0.1" -contrib-barcode = "0.1.0-beta3-preview5-SNAPSHOT" -contrib-locationwidget = "0.1.0-alpha01-preview-SNAPSHOT" +contrib-barcode = "0.1.0-beta3-preview7-SNAPSHOT" +contrib-locationwidget = "0.1.0-alpha01-preview2-SNAPSHOT" converter-gson = "2.9.0" core-ktx = "1.12.0" android-x-test= "1.5.2" core-testing = "2.2.0" coverallsGradlePlugin = "2.12.0" cqfFhirCr = "3.0.0-PRE9" -data-capture = "1.1.0-preview5-SNAPSHOT" +data-capture = "1.1.0-preview6-SNAPSHOT" datastore = "1.0.0" desugar-jdk-libs = "2.0.4" dokkaBase = "1.8.20" easy-rules-jexl = "4.1.0" espresso-core = "3.5.1" fhir-common-utils = "1.0.0-SNAPSHOT" -fhir-engine = "1.0.0-preview2-SNAPSHOT" -foundation = "1.6.1" +fhir-engine = "1.0.0-preview4-SNAPSHOT" +foundation = "1.6.3" fragment-ktx = "1.6.2" glide = "4.16.0" -gradle = "8.2.2" +gradle = "8.3.1" gson = "2.10.1" -hilt = "1.1.0" +hilt = "1.2.0" jjwt = "0.9.1" joda-time = "2.10.14" json = "20230618" @@ -39,7 +39,7 @@ junit-jupiter = "5.9.1" junit-ktx = "1.1.5" knowledge = "0.1.0-alpha03-preview2-SNAPSHOT" kotlin = "1.9.22" -kotlinx-coroutines = "1.7.2" +kotlinx-coroutines = "1.7.3" kotlinx-serialization-json = "1.6.0" kujaku-library = "0.9.0" ktlint = "0.50.0" @@ -47,8 +47,8 @@ leakcanary-android = "2.10" lifecycle= "2.7.0" mapbox-sdk-turf = "4.8.0" material = "1.11.0" -compose-material-icons = "1.6.1" -material3 = "1.2.0" +compose-material-icons = "1.6.3" +material3 = "1.2.1" mockk = "1.13.8" mockk-android = "1.13.8" msg-simple = "1.2" @@ -57,10 +57,8 @@ okhttp = "4.12.0" okhttp-logging-interceptor = "4.11.0" orchestrator = "1.4.2" p2p-lib = "0.6.9-SNAPSHOT" -paging-compose = "3.2.0" -paging-runtime-ktx = "3.2.0" -playServicesLocation = "21.0.1" -paging = "3.2.1" +androidx-paging = "3.2.0" +playServicesLocation = "21.2.0" preference-ktx = "1.2.1" prettytime = "5.0.2.Final" retrofit = "2.9.0" @@ -72,11 +70,11 @@ slf4j-nop = "1.7.36" spotlessPluginGradle = "6.25.0" stax-api = "1.0-2" timber = "5.0.1" -ui = "1.6.1" +ui = "1.6.3" work = "2.9.0" -workflow = "0.1.0-alpha04-preview6-SNAPSHOT" +workflow = "0.1.0-alpha04-preview8-SNAPSHOT" xercesImpl = "2.12.2" -jetbrains = "1.8.20" +jetbrains = "1.9.20" owasp = "8.2.1" kotlin-serialization = "1.8.10" dagger-hilt = "2.50" @@ -169,8 +167,8 @@ okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhtt okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp-logging-interceptor" } orchestrator = { group = "androidx.test", name = "orchestrator", version.ref = "orchestrator" } p2p-lib = { group = "org.smartregister", name = "p2p-lib", version.ref = "p2p-lib" } -paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging-compose" } -paging-runtime-ktx = { group = "androidx.paging", name = "paging-runtime-ktx", version.ref = "paging-runtime-ktx" } +paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "androidx-paging" } +paging-runtime-ktx = { group = "androidx.paging", name = "paging-runtime-ktx", version.ref = "androidx-paging" } play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "playServicesLocation" } preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference-ktx" } prettytime = { group = "org.ocpsoft.prettytime", name = "prettytime", version.ref = "prettytime" } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 68a1f59872..66ec8b608d 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/macrobenchmark/build.gradle.kts b/android/macrobenchmark/build.gradle.kts index 03564f6675..262980b39b 100644 --- a/android/macrobenchmark/build.gradle.kts +++ b/android/macrobenchmark/build.gradle.kts @@ -9,18 +9,18 @@ plugins { android { namespace = "org.smartregister.opensrp.quest.macrobenchmark" - compileSdk = 33 + compileSdk = BuildConfigs.compileSdk compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { jvmTarget = "1.8" } + kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() } defaultConfig { - minSdk = 24 - targetSdk = 33 + minSdk = BuildConfigs.minSdk + targetSdk = BuildConfigs.targetSdk testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR,DEBUGGABLE" diff --git a/android/quest/build.gradle.kts b/android/quest/build.gradle.kts index e9d7a2411f..2018a371d7 100644 --- a/android/quest/build.gradle.kts +++ b/android/quest/build.gradle.kts @@ -51,17 +51,17 @@ sonar { } android { - compileSdk = 34 + compileSdk = BuildConfigs.compileSdk val buildDate = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) namespace = "org.smartregister.fhircore.quest" defaultConfig { - applicationId = "org.smartregister.opensrp" - minSdk = 26 - versionCode = 10 - versionName = "1.1.0" + applicationId = BuildConfigs.applicationId + minSdk = BuildConfigs.minSdk + versionCode = BuildConfigs.versionCode + versionName = BuildConfigs.versionName multiDexEnabled = true buildConfigField("boolean", "SKIP_AUTH_CHECK", "false") @@ -161,7 +161,7 @@ android { buildConfig = true } - composeOptions { kotlinCompilerExtensionVersion = "1.5.8" } + composeOptions { kotlinCompilerExtensionVersion = BuildConfigs.kotlinCompilerExtensionVersion } testOptions { execution = "ANDROIDX_TEST_ORCHESTRATOR" @@ -173,7 +173,7 @@ android { } } - testCoverage { jacocoVersion = "0.8.11" } + testCoverage { jacocoVersion = BuildConfigs.jacocoVersion } lint { abortOnError = false } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireActivity.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireActivity.kt index f310d8612d..8275d70d65 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireActivity.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireActivity.kt @@ -350,41 +350,43 @@ class QuestionnaireActivity : BaseMultiLanguageActivity() { QuestionnaireFragment.SUBMIT_REQUEST_KEY, this, ) { _, _ -> - val questionnaireResponse = retrieveQuestionnaireResponse() + lifecycleScope.launch { + val questionnaireResponse = retrieveQuestionnaireResponse() - // Close questionnaire if opened in read only mode or if experimental - if (questionnaireConfig.isReadOnly() || questionnaire?.experimental == true) { - finish() - } - if (questionnaireResponse != null && questionnaire != null) { - viewModel.run { - setProgressState(QuestionnaireProgressState.ExtractionInProgress(true)) - - if (currentLocation != null) { - questionnaireResponse.contained.add( - ResourceUtils.createFhirLocationFromGpsLocation(gpsLocation = currentLocation!!), - ) - } + // Close questionnaire if opened in read only mode or if experimental + if (questionnaireConfig.isReadOnly() || questionnaire?.experimental == true) { + finish() + } + if (questionnaireResponse != null && questionnaire != null) { + viewModel.run { + setProgressState(QuestionnaireProgressState.ExtractionInProgress(true)) + + if (currentLocation != null) { + questionnaireResponse.contained.add( + ResourceUtils.createFhirLocationFromGpsLocation(gpsLocation = currentLocation!!), + ) + } - handleQuestionnaireSubmission( - questionnaire = questionnaire!!, - currentQuestionnaireResponse = questionnaireResponse, - questionnaireConfig = questionnaireConfig, - actionParameters = actionParameters, - context = this@QuestionnaireActivity, - ) { idTypes, questionnaireResponse -> - // Dismiss progress indicator dialog, submit result then finish activity - // TODO Ensure this dialog is dismissed even when an exception is encountered - setProgressState(QuestionnaireProgressState.ExtractionInProgress(false)) - setResult( - Activity.RESULT_OK, - Intent().apply { - putExtra(QUESTIONNAIRE_RESPONSE, questionnaireResponse as Serializable) - putExtra(QUESTIONNAIRE_SUBMISSION_EXTRACTED_RESOURCE_IDS, idTypes as Serializable) - putExtra(QUESTIONNAIRE_CONFIG, questionnaireConfig as Parcelable) - }, - ) - finish() + handleQuestionnaireSubmission( + questionnaire = questionnaire!!, + currentQuestionnaireResponse = questionnaireResponse, + questionnaireConfig = questionnaireConfig, + actionParameters = actionParameters, + context = this@QuestionnaireActivity, + ) { idTypes, questionnaireResponse -> + // Dismiss progress indicator dialog, submit result then finish activity + // TODO Ensure this dialog is dismissed even when an exception is encountered + setProgressState(QuestionnaireProgressState.ExtractionInProgress(false)) + setResult( + Activity.RESULT_OK, + Intent().apply { + putExtra(QUESTIONNAIRE_RESPONSE, questionnaireResponse as Serializable) + putExtra(QUESTIONNAIRE_SUBMISSION_EXTRACTED_RESOURCE_IDS, idTypes as Serializable) + putExtra(QUESTIONNAIRE_CONFIG, questionnaireConfig as Parcelable) + }, + ) + finish() + } } } } @@ -402,8 +404,10 @@ class QuestionnaireActivity : BaseMultiLanguageActivity() { .questionnaire_in_progress_alert_back_pressed_message, title = org.smartregister.fhircore.engine.R.string.questionnaire_alert_back_pressed_title, confirmButtonListener = { - retrieveQuestionnaireResponse()?.let { questionnaireResponse -> - viewModel.saveDraftQuestionnaire(questionnaireResponse) + lifecycleScope.launch { + retrieveQuestionnaireResponse()?.let { questionnaireResponse -> + viewModel.saveDraftQuestionnaire(questionnaireResponse) + } } }, confirmButtonText = @@ -426,7 +430,7 @@ class QuestionnaireActivity : BaseMultiLanguageActivity() { } } - private fun retrieveQuestionnaireResponse(): QuestionnaireResponse? = + private suspend fun retrieveQuestionnaireResponse(): QuestionnaireResponse? = (supportFragmentManager.findFragmentByTag(QUESTIONNAIRE_FRAGMENT_TAG) as QuestionnaireFragment?) ?.getQuestionnaireResponse() diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt index 811bd04452..22ea7e0bfd 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt @@ -645,7 +645,7 @@ constructor( * result of [QuestionnaireResponseValidator] are [Valid] or [NotValidated] (validation is * optional on [Questionnaire] fields) */ - fun validateQuestionnaireResponse( + suspend fun validateQuestionnaireResponse( questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, context: Context, diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModelTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModelTest.kt index 33a838fabf..95a42b2f8b 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModelTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModelTest.kt @@ -37,7 +37,6 @@ import io.mockk.runs import io.mockk.slot import io.mockk.spyk import io.mockk.unmockkObject -import io.mockk.verify import java.util.Date import java.util.UUID import javax.inject.Inject @@ -266,7 +265,7 @@ class QuestionnaireViewModelTest : RobolectricTest() { ) // Verify QuestionnaireResponse was validated - verify { + coVerify { questionnaireViewModel.validateQuestionnaireResponse( questionnaire = questionnaire, questionnaireResponse = questionnaireResponse, @@ -658,29 +657,31 @@ class QuestionnaireViewModelTest : RobolectricTest() { ) } - // No answer provided - Assert.assertFalse( - questionnaireViewModel.validateQuestionnaireResponse( - questionnaire, - questionnaireResponse, - context, - ), - ) + runBlocking { + // No answer provided + Assert.assertFalse( + questionnaireViewModel.validateQuestionnaireResponse( + questionnaire, + questionnaireResponse, + context, + ), + ) - // With an answer provided - Assert.assertTrue( - questionnaireViewModel.validateQuestionnaireResponse( - questionnaire, - questionnaireResponse.apply { - itemFirstRep.answer = - listOf( - QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent() - .setValue(StringType("Answer")), - ) - }, - context, - ), - ) + // With an answer provided + Assert.assertTrue( + questionnaireViewModel.validateQuestionnaireResponse( + questionnaire, + questionnaireResponse.apply { + itemFirstRep.answer = + listOf( + QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent() + .setValue(StringType("Answer")), + ) + }, + context, + ), + ) + } } @Test @@ -708,7 +709,7 @@ class QuestionnaireViewModelTest : RobolectricTest() { "http://smartreg.org/Library/123", patient.asReference().reference, null, - setOf(), + expressions = setOf(), ) } }